diff --git a/.cargo/config.toml b/.cargo/config.toml
index 66da12a13b11..3082e9635cf9 100644
--- a/.cargo/config.toml
+++ b/.cargo/config.toml
@@ -17,6 +17,15 @@ rustflags = [
     # "-Wmissing_docs",
     "-Wrust_2018_idioms",
     "-Wunused_qualifications",
+    "--cfg",
+    "uuid_unstable"
+]
+
+
+[build]
+rustdocflags = [
+    "--cfg",
+    "uuid_unstable"
 ]
 
 [alias]
diff --git a/.dockerignore b/.dockerignore
index 35515ecf138d..62804a712fa1 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,17 +1,267 @@
-target
-openapi
-monitoring
-logs
-docs
-connector-template
-.cargo
-.vscode
-postman
-kubernetes
-*Dockerfile
+# Created by https://www.toptal.com/developers/gitignore/api/rust,visualstudiocode,clion,dotenv,direnv,linux,macos,windows
+# Edit at https://www.toptal.com/developers/gitignore?templates=rust,visualstudiocode,clion,dotenv,direnv,linux,macos,windows
+
+### CLion ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# AWS User-specific
+.idea/**/aws.xml
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn.  Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# SonarLint plugin
+.idea/sonarlint/
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### CLion Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+# https://plugins.jetbrains.com/plugin/7973-sonarlint
+.idea/**/sonarlint/
+
+# SonarQube Plugin
+# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
+.idea/**/sonarIssues.xml
+
+# Markdown Navigator plugin
+# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
+.idea/**/markdown-navigator.xml
+.idea/**/markdown-navigator-enh.xml
+.idea/**/markdown-navigator/
+
+# Cache file creation bug
+# See https://youtrack.jetbrains.com/issue/JBR-2257
+.idea/$CACHE_FILE$
+
+# CodeStream plugin
+# https://plugins.jetbrains.com/plugin/12206-codestream
+.idea/codestream.xml
+
+# Azure Toolkit for IntelliJ plugin
+# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
+.idea/**/azureSettings.xml
+
+### direnv ###
+.direnv
+.envrc
+
+### dotenv ###
 .env
-.dockerignore
-.gitignore
-Makefile
-*.sh
-Jenkinsfile
\ No newline at end of file
+
+### Linux ###
+*~
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+### macOS ###
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+### macOS Patch ###
+# iCloud generated files
+*.icloud
+
+### Rust ###
+# Generated by Cargo
+# will have compiled files and executables
+debug/
+target/
+
+# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
+# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
+!Cargo.lock
+
+# These are backup files generated by rustfmt
+**/*.rs.bk
+
+# MSVC Windows builds of rustc generate these, which store debugging information
+*.pdb
+
+### VisualStudioCode ###
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+!.vscode/*.code-snippets
+
+# Local History for Visual Studio Code
+.history/
+
+# Built Visual Studio Code Extensions
+*.vsix
+
+### VisualStudioCode Patch ###
+# Ignore all local history of files
+.history
+.ionide
+
+# Support for Project snippet scope
+.vscode/*.code-snippets
+
+# Ignore code-workspaces
+*.code-workspace
+
+### Windows ###
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# End of https://www.toptal.com/developers/gitignore/api/rust,visualstudiocode,clion,dotenv,direnv,linux,macos,windows
+
+# hyperswitch Project specific excludes
+# code coverage report
+*.profraw
+html/
+coverage.json
+# other
+logs/
+**/tmp
+**/*.log
+**/*.log.*
+monitoring/*.tmp/
+config/sandbox.toml
+config/production.toml
+!loadtest/.env
+loadtest/*.tmp/
+
+# Nix output
+result*
+
+.idea/
+
+# node_modules
+node_modules/
+
+**/connector_auth.toml
+**/sample_auth.toml
+**/auth.toml
diff --git a/.github/secrets/connector_auth.toml.gpg b/.github/secrets/connector_auth.toml.gpg
index ae8c09612643..487e436df463 100644
Binary files a/.github/secrets/connector_auth.toml.gpg and b/.github/secrets/connector_auth.toml.gpg differ
diff --git a/.github/workflows/conventional-commit-check.yml b/.github/workflows/conventional-commit-check.yml
index c02d8a3bfb49..5fd25e9332d1 100644
--- a/.github/workflows/conventional-commit-check.yml
+++ b/.github/workflows/conventional-commit-check.yml
@@ -53,8 +53,10 @@ jobs:
         id: pr_title_check
         if: ${{ github.event_name == 'pull_request_target' }}
         shell: bash
+        env:
+          TITLE: ${{ github.event.pull_request.title }}
         continue-on-error: true
-        run: cog verify '${{ github.event.pull_request.title }}'
+        run: cog verify "$TITLE"
 
       - name: Verify commit message follows conventional commit standards
         id: commit_message_check
diff --git a/.github/workflows/postman-collection-runner.yml b/.github/workflows/postman-collection-runner.yml
index 6b0911d1b456..3291755b56cf 100644
--- a/.github/workflows/postman-collection-runner.yml
+++ b/.github/workflows/postman-collection-runner.yml
@@ -143,7 +143,7 @@ jobs:
 
           for i in $(echo "$CONNECTORS" | tr "," "\n"); do
             echo $i
-            if ! cargo run --bin test_utils -- --connector_name="$i" --base_url="$BASE_URL" --admin_api_key="$ADMIN_API_KEY"; then
+            if ! cargo run --bin test_utils -- --connector-name="$i" --base-url="$BASE_URL" --admin-api-key="$ADMIN_API_KEY"; then
               failed_connectors+=("$i")
             fi
           done
diff --git a/.github/workflows/pr-title-spell-check.yml b/.github/workflows/pr-title-spell-check.yml
new file mode 100644
index 000000000000..6ab6f184739d
--- /dev/null
+++ b/.github/workflows/pr-title-spell-check.yml
@@ -0,0 +1,27 @@
+name: PR Title Spell Check
+
+on:
+  pull_request:
+    types:
+      - opened
+      - edited
+      - synchronize
+
+jobs:
+  typos:
+    name: Spell check PR title
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v3
+
+      - name: Store PR title in a file
+        shell: bash
+        env: 
+          TITLE: ${{ github.event.pull_request.title }} 
+        run: echo $TITLE > pr_title.txt
+
+      - name: Spell check
+        uses: crate-ci/typos@master
+        with:
+          files: ./pr_title.txt
diff --git a/.github/workflows/release-new-version.yml b/.github/workflows/release-new-version.yml
index 4b2995174922..872c207e8aa3 100644
--- a/.github/workflows/release-new-version.yml
+++ b/.github/workflows/release-new-version.yml
@@ -74,20 +74,31 @@ jobs:
             connector=$(basename ${connector_dir})
             newman dir-import ${POSTMAN_DIR}/${connector} -o ${POSTMAN_JSON_DIR}/${connector}.postman_collection.json
           done
-          (git diff --quiet && git diff --staged --quiet) || (git commit -am 'test(postman): update postman collection files' && echo "Committed changes") || (echo "Unable to commit the following changes:" && git diff)
+
+          if git add postman && ! git diff --staged --quiet postman; then
+            git commit --message 'test(postman): update postman collection files'
+            echo "Changes detected and commited."
+          fi
 
       - name: Obtain previous and new tag information
         shell: bash
         # Only consider tags on current branch when setting PREVIOUS_TAG
         run: |
-          echo "PREVIOUS_TAG=$(git tag --sort='version:refname' --merged | tail --lines 1)" >> $GITHUB_ENV
-          echo "NEW_TAG=$(cog bump --auto --dry-run)" >> $GITHUB_ENV
+          PREVIOUS_TAG="$(git tag --sort='version:refname' --merged | tail --lines 1)"
+          if [[ "$(cog bump --auto --dry-run)" == *"No conventional commits for your repository that required a bump"* ]]; then
+            NEW_TAG="$(cog bump --patch --dry-run)"
+          elif [[ "${PREVIOUS_TAG}" != "${NEW_TAG}" ]]; then
+            NEW_TAG="$(cog bump --auto --dry-run)"
+          fi
+          echo "NEW_TAG=${NEW_TAG}" >> $GITHUB_ENV
+          echo "PREVIOUS_TAG=${PREVIOUS_TAG}" >> $GITHUB_ENV
 
       - name: Update changelog and create tag
         shell: bash
         if: ${{ env.NEW_TAG != env.PREVIOUS_TAG }}
+        # Remove prefix 'v' from 'NEW_TAG' as cog bump --version expects only the version number
         run: |
-          cog bump --auto
+          cog bump --version ${NEW_TAG#v}
 
       - name: Push created commit and tag
         shell: bash
diff --git a/.typos.toml b/.typos.toml
index 8ed1c84a5bb5..1ac38a005c9e 100644
--- a/.typos.toml
+++ b/.typos.toml
@@ -34,9 +34,11 @@ unsuccess = "unsuccess"       # Used in cryptopay request
 ba = "ba" # ignore minor commit conversions
 ede = "ede" # ignore minor commit conversions
 daa = "daa" # Commit id
+afe = "afe" # Commit id
 
 [files]
 extend-exclude = [
     "config/redis.conf", # `typos` also checked "AKE" in the file, which is present as a quoted string
     "openapi/open_api_spec.yaml", # no longer updated
+    "crates/router/src/utils/user/blocker_emails.txt", # this file contains various email domains
 ]
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3a0cc5458623..e5da650def02 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,460 @@ All notable changes to HyperSwitch will be documented here.
 
 - - -
 
+## 1.78.0 (2023-11-14)
+
+### Features
+
+- **router:** Add automatic retries and step up 3ds flow ([#2834](https://github.com/juspay/hyperswitch/pull/2834)) ([`d2968c9`](https://github.com/juspay/hyperswitch/commit/d2968c94978a57422fa46a8195d906736a95b864))
+- Payment link status page UI ([#2740](https://github.com/juspay/hyperswitch/pull/2740)) ([`856c7af`](https://github.com/juspay/hyperswitch/commit/856c7af77e17599ca0d4d119744ac582e9c3c971))
+
+### Bug Fixes
+
+- Handle session and confirm flow discrepancy in surcharge details ([#2696](https://github.com/juspay/hyperswitch/pull/2696)) ([`cafea45`](https://github.com/juspay/hyperswitch/commit/cafea45982d7b520fe68fde967984ce88f68c6c0))
+
+**Full Changelog:** [`v1.77.0...v1.78.0`](https://github.com/juspay/hyperswitch/compare/v1.77.0...v1.78.0)
+
+- - -
+
+
+## 1.77.0 (2023-11-13)
+
+### Features
+
+- **apievent:** Added hs latency to api event ([#2734](https://github.com/juspay/hyperswitch/pull/2734)) ([`c124511`](https://github.com/juspay/hyperswitch/commit/c124511052ed8911a2ccfcf648c0793b5c1ca690))
+- **router:**
+  - Add new JWT authentication variants and use them ([#2835](https://github.com/juspay/hyperswitch/pull/2835)) ([`f88eee7`](https://github.com/juspay/hyperswitch/commit/f88eee7362be2cc3e8e8dc2bb7bfd263892ff01e))
+  - Profile specific fallback derivation while routing payments ([#2806](https://github.com/juspay/hyperswitch/pull/2806)) ([`8e538db`](https://github.com/juspay/hyperswitch/commit/8e538dbd5c189047d0a0b24fa752b9a1c67554f5))
+
+### Build System / Dependencies
+
+- **deps:** Remove unused dependencies and features ([#2854](https://github.com/juspay/hyperswitch/pull/2854)) ([`0553587`](https://github.com/juspay/hyperswitch/commit/05535871152f4a6ac24ce6b5b5390da13cc29b96))
+
+**Full Changelog:** [`v1.76.0...v1.77.0`](https://github.com/juspay/hyperswitch/compare/v1.76.0...v1.77.0)
+
+- - -
+
+
+## 1.76.0 (2023-11-12)
+
+### Features
+
+- **analytics:** Analytics APIs  ([#2792](https://github.com/juspay/hyperswitch/pull/2792)) ([`f847802`](https://github.com/juspay/hyperswitch/commit/f847802339bfedb24cbaa47ad55e31d80cefddca))
+- **router:** Added Payment link new design ([#2731](https://github.com/juspay/hyperswitch/pull/2731)) ([`2a4f5d1`](https://github.com/juspay/hyperswitch/commit/2a4f5d13717a78dc2e2e4fc9a492a45b92151dbe))
+- **user:** Setup user tables ([#2803](https://github.com/juspay/hyperswitch/pull/2803)) ([`20c4226`](https://github.com/juspay/hyperswitch/commit/20c4226a36e4650a3ba8811b758ac5f7969bcfb3))
+
+### Refactors
+
+- **connector:** [Zen] change error message from NotSupported to NotImplemented ([#2831](https://github.com/juspay/hyperswitch/pull/2831)) ([`b5ea8db`](https://github.com/juspay/hyperswitch/commit/b5ea8db2d2b7e7544931704a7191b42d3a8299be))
+- **core:** Remove connector response table and use payment_attempt instead ([#2644](https://github.com/juspay/hyperswitch/pull/2644)) ([`966369b`](https://github.com/juspay/hyperswitch/commit/966369b6f2c205b59524c23ad3b21ebab547631f))
+- **events:** Update api events to follow snake case naming ([#2828](https://github.com/juspay/hyperswitch/pull/2828)) ([`b3d5062`](https://github.com/juspay/hyperswitch/commit/b3d5062dc07676ec12e903b1999fdd9138c0891d))
+
+### Documentation
+
+- **README:** Add bootstrap button for cloudformation deployment ([#2827](https://github.com/juspay/hyperswitch/pull/2827)) ([`e67e808`](https://github.com/juspay/hyperswitch/commit/e67e808d70d41c371fff168824e5a4dbb8b3a040))
+
+**Full Changelog:** [`v1.75.0...v1.76.0`](https://github.com/juspay/hyperswitch/compare/v1.75.0...v1.76.0)
+
+- - -
+
+
+## 1.75.0 (2023-11-09)
+
+### Features
+
+- **events:** Add extracted fields based on req/res types ([#2795](https://github.com/juspay/hyperswitch/pull/2795)) ([`8985794`](https://github.com/juspay/hyperswitch/commit/89857941b09c5fbe0f3e7d5b4f908bb144ae162d))
+- **router:**
+  - Added merchant custom name support for payment link ([#2685](https://github.com/juspay/hyperswitch/pull/2685)) ([`8b15189`](https://github.com/juspay/hyperswitch/commit/8b151898dc0d8eefe5ed2bbdafe59e8f58b4698c))
+  - Add `gateway_status_map` CRUD APIs ([#2809](https://github.com/juspay/hyperswitch/pull/2809)) ([`5c9e235`](https://github.com/juspay/hyperswitch/commit/5c9e235bd30dd3e03d086a83613edfcc62b2ead2))
+
+### Bug Fixes
+
+- **analytics:** Added hs latency to api event for paymentconfirm call ([#2787](https://github.com/juspay/hyperswitch/pull/2787)) ([`aab8f60`](https://github.com/juspay/hyperswitch/commit/aab8f6035c16ca19009f8f1e0db688c17bc0b2b6))
+- [mollie] locale validation irrespective of auth type ([#2814](https://github.com/juspay/hyperswitch/pull/2814)) ([`25a73c2`](https://github.com/juspay/hyperswitch/commit/25a73c29a4c4715a54862dd6a28c875fd3752f63))
+
+**Full Changelog:** [`v1.74.0...v1.75.0`](https://github.com/juspay/hyperswitch/compare/v1.74.0...v1.75.0)
+
+- - -
+
+
+## 1.74.0 (2023-11-08)
+
+### Features
+
+- **core:** Use redis as temp locker instead of basilisk ([#2789](https://github.com/juspay/hyperswitch/pull/2789)) ([`6678689`](https://github.com/juspay/hyperswitch/commit/6678689265ae9a4fbb7a43c1938237d349c5a68e))
+- **events:** Add request details to api events ([#2769](https://github.com/juspay/hyperswitch/pull/2769)) ([`164d1c6`](https://github.com/juspay/hyperswitch/commit/164d1c66fbcb84104db07412496114db2f8c5c0c))
+- **router:** Add `gateway_status_map` interface ([#2804](https://github.com/juspay/hyperswitch/pull/2804)) ([`a429b23`](https://github.com/juspay/hyperswitch/commit/a429b23c7f21c9d08a79895c0b770b35aab725f7))
+- **test_utils:** Add custom-headers and custom delay support to rustman ([#2636](https://github.com/juspay/hyperswitch/pull/2636)) ([`1effddd`](https://github.com/juspay/hyperswitch/commit/1effddd0a0d3985d6df03c4ae9be28712befc05e))
+
+### Bug Fixes
+
+- **connector:** Add attempt_status in field in error_response ([#2794](https://github.com/juspay/hyperswitch/pull/2794)) ([`5642fef`](https://github.com/juspay/hyperswitch/commit/5642fef52a6d591d12c5745ed381f41a1593f183))
+
+### Refactors
+
+- **config:** Update payment method filter of Klarna in Stripe ([#2807](https://github.com/juspay/hyperswitch/pull/2807)) ([`21ce807`](https://github.com/juspay/hyperswitch/commit/21ce8079f4cb11d70c5eaae78f83773141c67d0c))
+- **router:** Add parameter connectors to get_request_body function ([#2708](https://github.com/juspay/hyperswitch/pull/2708)) ([`7623ea9`](https://github.com/juspay/hyperswitch/commit/7623ea93bee61b0bb22b68e86f44de17f04f876b))
+
+### Documentation
+
+- **README:** Update README ([#2800](https://github.com/juspay/hyperswitch/pull/2800)) ([`bef0a04`](https://github.com/juspay/hyperswitch/commit/bef0a04edc6323b3b7a2e0dd7eeb7954915ba7cf))
+
+**Full Changelog:** [`v1.73.0...v1.74.0`](https://github.com/juspay/hyperswitch/compare/v1.73.0...v1.74.0)
+
+- - -
+
+
+## 1.73.0 (2023-11-07)
+
+### Features
+
+- **connector:**
+  - [BANKOFAMERICA] Add Connector Template Code ([#2764](https://github.com/juspay/hyperswitch/pull/2764)) ([`4563935`](https://github.com/juspay/hyperswitch/commit/4563935372d2cdff3f746fa86a47f1166ffd32ac))
+  - [Bitpay] Add order id as the reference id ([#2591](https://github.com/juspay/hyperswitch/pull/2591)) ([`d47d4ac`](https://github.com/juspay/hyperswitch/commit/d47d4ac682705d6ac692f9381149bbf08ad71264))
+- **router:** Make webhook events config disabled only and by default enable all the events ([#2770](https://github.com/juspay/hyperswitch/pull/2770)) ([`d335879`](https://github.com/juspay/hyperswitch/commit/d335879f9289b57a90a76c6587a58a0b3e12c9ad))
+- Make drainer logs queryable with request_id and global_id ([#2771](https://github.com/juspay/hyperswitch/pull/2771)) ([`ff73aba`](https://github.com/juspay/hyperswitch/commit/ff73aba8e72d8e072027881760335c0c818df665))
+
+### Bug Fixes
+
+- **connector:** Fix amount conversion incase of minor unit  ([#2793](https://github.com/juspay/hyperswitch/pull/2793)) ([`34f5226`](https://github.com/juspay/hyperswitch/commit/34f52260d3fa68b54e5b46207afaf2ad07a8d8ba))
+
+### Refactors
+
+- **payment_methods:** Added support for account subtype in pmd ([#2651](https://github.com/juspay/hyperswitch/pull/2651)) ([`e7375d0`](https://github.com/juspay/hyperswitch/commit/e7375d0e26099a7e0e6efd1b83b8eb9c7b1c5411))
+
+### Documentation
+
+- **README:** Add one-click deployment information using CDK ([#2798](https://github.com/juspay/hyperswitch/pull/2798)) ([`bb39cd4`](https://github.com/juspay/hyperswitch/commit/bb39cd4081fdcaf68b2b5de2234e93493dbd84b6))
+
+**Full Changelog:** [`v1.72.0...v1.73.0`](https://github.com/juspay/hyperswitch/compare/v1.72.0...v1.73.0)
+
+- - -
+
+
+## 1.72.0 (2023-11-05)
+
+### Features
+
+- **connector:**
+  - [ACI] Currency Unit Conversion ([#2750](https://github.com/juspay/hyperswitch/pull/2750)) ([`cdead78`](https://github.com/juspay/hyperswitch/commit/cdead78ea6a1f2dce92187f499f54498ba4bb173))
+  - [Fiserv] Currency Unit Conversion ([#2715](https://github.com/juspay/hyperswitch/pull/2715)) ([`b6b9e4f`](https://github.com/juspay/hyperswitch/commit/b6b9e4f912e1c61cd31ab91be587ffb08c9f3a5b))
+  - [Bitpay] Use `connector_request_reference_id` as reference to the connector ([#2697](https://github.com/juspay/hyperswitch/pull/2697)) ([`7141b89`](https://github.com/juspay/hyperswitch/commit/7141b89d231bae0c3b1c10095b88df16129b1665))
+  - [NMI] Currency Unit Conversion ([#2707](https://github.com/juspay/hyperswitch/pull/2707)) ([`1b45a30`](https://github.com/juspay/hyperswitch/commit/1b45a302630ed8affc5abff0de1325fb5c6f870e))
+  - [Payeezy] Currency Unit Conversion ([#2710](https://github.com/juspay/hyperswitch/pull/2710)) ([`25245b9`](https://github.com/juspay/hyperswitch/commit/25245b965371d93449f4584667adeb38ab7e0e59))
+
+### Refactors
+
+- **connector:** [Stax] Currency Unit Conversion ([#2711](https://github.com/juspay/hyperswitch/pull/2711)) ([`2782923`](https://github.com/juspay/hyperswitch/commit/278292322c7c06f4239dd73861469e436bd941fa))
+
+### Testing
+
+- **postman:** Update postman collection files ([`d11e7fd`](https://github.com/juspay/hyperswitch/commit/d11e7fd5642efe7da4b5021d87cf40f16d9eeded))
+
+**Full Changelog:** [`v1.71.0...v1.72.0`](https://github.com/juspay/hyperswitch/compare/v1.71.0...v1.72.0)
+
+- - -
+
+
+## 1.71.0 (2023-11-03)
+
+### Features
+
+- **merchant_connector_account:** Add cache for querying by `merchant_connector_id` ([#2738](https://github.com/juspay/hyperswitch/pull/2738)) ([`1ba6282`](https://github.com/juspay/hyperswitch/commit/1ba6282699b7dff5e6e95c9a14e51c0f8bf749cd))
+- **router:** Add Smart Routing to route payments efficiently ([#2665](https://github.com/juspay/hyperswitch/pull/2665)) ([`9b618d2`](https://github.com/juspay/hyperswitch/commit/9b618d24476967d364835d04010d9076a80aeb9c))
+
+### Bug Fixes
+
+- **connector:**
+  - [Cryptopay]Remove default case handling for Cryptopay ([#2699](https://github.com/juspay/hyperswitch/pull/2699)) ([`255a4f8`](https://github.com/juspay/hyperswitch/commit/255a4f89a8e0124310d42bb63ad459bd8cde2cba))
+  - [Bluesnap] fix psync status to failure when it is '403'  ([#2772](https://github.com/juspay/hyperswitch/pull/2772)) ([`9314d14`](https://github.com/juspay/hyperswitch/commit/9314d1446326fd8a69f1f69657a976bbe7c27901))
+- Response spelling ([#2779](https://github.com/juspay/hyperswitch/pull/2779)) ([`5859372`](https://github.com/juspay/hyperswitch/commit/585937204d9071baa37d402f73159f8f650d0a07))
+
+### Testing
+
+- **postman:** Update postman collection files ([`21e8a10`](https://github.com/juspay/hyperswitch/commit/21e8a105f9b47ded232b457a0420ad71ec2414ed))
+
+**Full Changelog:** [`v1.70.1...v1.71.0`](https://github.com/juspay/hyperswitch/compare/v1.70.1...v1.71.0)
+
+- - -
+
+
+## 1.70.1 (2023-11-03)
+
+### Revert
+
+- Fix(analytics): feat(analytics): analytics APIs ([#2777](https://github.com/juspay/hyperswitch/pull/2777)) ([`169d33b`](https://github.com/juspay/hyperswitch/commit/169d33bf8157b1a9910c841c8c55eddc4d2ad168))
+
+**Full Changelog:** [`v1.70.0...v1.70.1`](https://github.com/juspay/hyperswitch/compare/v1.70.0...v1.70.1)
+
+- - -
+
+
+## 1.70.0 (2023-11-03)
+
+### Features
+
+- **analytics:** Analytics APIs ([#2676](https://github.com/juspay/hyperswitch/pull/2676)) ([`c0a5e7b`](https://github.com/juspay/hyperswitch/commit/c0a5e7b7d945095053606e35c9bb23a06090c4e3))
+- **connector:** [Multisafepay] add error handling ([#2595](https://github.com/juspay/hyperswitch/pull/2595)) ([`b3c846d`](https://github.com/juspay/hyperswitch/commit/b3c846d637dd32a2d6d7044c118abbb2616642f0))
+- **events:** Add api auth type details to events ([#2760](https://github.com/juspay/hyperswitch/pull/2760)) ([`1094493`](https://github.com/juspay/hyperswitch/commit/10944937a02502e0727f16368d8d055e575dd518))
+
+### Bug Fixes
+
+- **router:** Make customer_id optional when billing and shipping address is passed in payments create, update ([#2762](https://github.com/juspay/hyperswitch/pull/2762)) ([`e40a293`](https://github.com/juspay/hyperswitch/commit/e40a29351c7aa7b86a5684959a84f0236104cafd))
+- Null fields in payments response ([#2745](https://github.com/juspay/hyperswitch/pull/2745)) ([`42261a5`](https://github.com/juspay/hyperswitch/commit/42261a5306bb99d3e20eb3aa734a895e589b1d94))
+
+### Testing
+
+- **postman:** Update postman collection files ([`772f03e`](https://github.com/juspay/hyperswitch/commit/772f03ee3836ce86de3874f6a5e7f636718e6034))
+
+**Full Changelog:** [`v1.69.0...v1.70.0`](https://github.com/juspay/hyperswitch/compare/v1.69.0...v1.70.0)
+
+- - -
+
+
+## 1.69.0 (2023-10-31)
+
+### Features
+
+- **connector:**
+  - [VOLT] Implement payment flows and bank redirect payment method ([#2582](https://github.com/juspay/hyperswitch/pull/2582)) ([`23bd364`](https://github.com/juspay/hyperswitch/commit/23bd364a7819a48c3f5f89ff5b71cc237d6e2d46))
+  - [NMI] add orderid to PaymentRequest ([#2727](https://github.com/juspay/hyperswitch/pull/2727)) ([`aad3f0f`](https://github.com/juspay/hyperswitch/commit/aad3f0f6fafdb08f1c5f1feb2588d6d0fb9162ff))
+  - Worldline Use `connector_response_reference_id` as reference to merchant ([#2721](https://github.com/juspay/hyperswitch/pull/2721)) ([`a261f1a`](https://github.com/juspay/hyperswitch/commit/a261f1a2fce84354b3741429b629928d1bd06aab))
+  - [Authorizedotnet] Use connector_request_reference_id as reference to the connector ([#2593](https://github.com/juspay/hyperswitch/pull/2593)) ([`3d7c6b0`](https://github.com/juspay/hyperswitch/commit/3d7c6b004d5f6399858925b40c3010fca486bbd5))
+  - [Multisafepay] Currency Unit Conversion ([#2679](https://github.com/juspay/hyperswitch/pull/2679)) ([`42b13f7`](https://github.com/juspay/hyperswitch/commit/42b13f737a53143057ab23867f32017ea8c17780))
+  - [Iatapay] currency unit conversion ([#2592](https://github.com/juspay/hyperswitch/pull/2592)) ([`0f5406c`](https://github.com/juspay/hyperswitch/commit/0f5406c620e9cdd20841898e9451a35f434f5b8a))
+  - [BitPay] Currency Unit Conversion ([#2736](https://github.com/juspay/hyperswitch/pull/2736)) ([`e377279`](https://github.com/juspay/hyperswitch/commit/e377279d9cc872238fcfd8de324b44b0249b95c2))
+- **organization:** Add organization table ([#2669](https://github.com/juspay/hyperswitch/pull/2669)) ([`d682471`](https://github.com/juspay/hyperswitch/commit/d6824710015b134a50986b3e85d3840902322711))
+- Add one-click deploy script for HyperSwitch on AWS (EC2, RDS, Redis) ([#2730](https://github.com/juspay/hyperswitch/pull/2730)) ([`838372a`](https://github.com/juspay/hyperswitch/commit/838372ab3f6f3f35b8d884958810bab54cc17244))
+- Implement list_merchant_connector_accounts_by_merchant_id_connector_name function ([#2742](https://github.com/juspay/hyperswitch/pull/2742)) ([`15a6b5a`](https://github.com/juspay/hyperswitch/commit/15a6b5a855def5650e16b96e6529ad7fa0845e6b))
+
+### Bug Fixes
+
+- **connector:** [Stripe] add decline_code in error_reason ([#2735](https://github.com/juspay/hyperswitch/pull/2735)) ([`0a44f56`](https://github.com/juspay/hyperswitch/commit/0a44f5699ed7b0c0ea0352b67c65df496ebe61f3))
+- **typo:** Add commit id to allowed typos ([#2733](https://github.com/juspay/hyperswitch/pull/2733)) ([`8984627`](https://github.com/juspay/hyperswitch/commit/8984627d1cfd1a773e931617a3351884b12399a5))
+- Make kv log extraction easier ([#2666](https://github.com/juspay/hyperswitch/pull/2666)) ([`577ef1a`](https://github.com/juspay/hyperswitch/commit/577ef1ae1a4718aaf90175d49e2a786af255fd63))
+
+### Refactors
+
+- **connector:**
+  - [Noon] Remove Default Case Handling ([#2677](https://github.com/juspay/hyperswitch/pull/2677)) ([`452090d`](https://github.com/juspay/hyperswitch/commit/452090d56d713a5cc5c8fae3cc2f9f3d26e27a53))
+  - [Payme] Remove Default Case Handling ([#2719](https://github.com/juspay/hyperswitch/pull/2719)) ([`94947bd`](https://github.com/juspay/hyperswitch/commit/94947bdb33ca4eb91daad13b2a427592d3b69851))
+  - [Payeezy] remove default case handling ([#2712](https://github.com/juspay/hyperswitch/pull/2712)) ([`ceed76f`](https://github.com/juspay/hyperswitch/commit/ceed76fb2e67771048e563a13703eb801eeaae08))
+- **core:** Use `business_profile` to read merchant configs ([#2729](https://github.com/juspay/hyperswitch/pull/2729)) ([`8c85173`](https://github.com/juspay/hyperswitch/commit/8c85173ecdd13db5ec7c4c0fe18456a31c8ee57e))
+- **db:** Migrate to payment_attempt from connector_response  ([#2656](https://github.com/juspay/hyperswitch/pull/2656)) ([`9d9fc2a`](https://github.com/juspay/hyperswitch/commit/9d9fc2a8c5e9e30ed7ed4eeb2417365fc06be711))
+
+### Testing
+
+- **postman:** Update postman collection files ([`db8f58b`](https://github.com/juspay/hyperswitch/commit/db8f58b145feef371c958086a1ec02128680d018))
+
+### Miscellaneous Tasks
+
+- **env:** Add ttl as env variable ([#2653](https://github.com/juspay/hyperswitch/pull/2653)) ([`8b1499e`](https://github.com/juspay/hyperswitch/commit/8b1499e121678c5df3ca0197e2ec14074fd96eb5))
+
+**Full Changelog:** [`v1.68.0...v1.69.0`](https://github.com/juspay/hyperswitch/compare/v1.68.0...v1.69.0)
+
+- - -
+
+
+## 1.68.0 (2023-10-29)
+
+### Features
+
+- **connector:**
+  - [OpenNode] Currency Unit Conversion ([#2645](https://github.com/juspay/hyperswitch/pull/2645)) ([`88e1f29`](https://github.com/juspay/hyperswitch/commit/88e1f29dae13622bc58b8f5df1cd84b929b28ac6))
+  - [Mollie] Currency Unit Conversion ([#2671](https://github.com/juspay/hyperswitch/pull/2671)) ([`3578db7`](https://github.com/juspay/hyperswitch/commit/3578db7640d8eda8f063e11b8bb64452fb987eef))
+  - [Dlocal] Implement feature to use connector_request_reference_id as reference to the connector ([#2704](https://github.com/juspay/hyperswitch/pull/2704)) ([`af90089`](https://github.com/juspay/hyperswitch/commit/af90089010e06ed45a70c51d4143260eec45b6dc))
+- **events:** Add masked json serializer for logging PII values ([#2681](https://github.com/juspay/hyperswitch/pull/2681)) ([`13c66df`](https://github.com/juspay/hyperswitch/commit/13c66df92c5b7db9e44852d4afee7a4e5ae52a15))
+
+### Bug Fixes
+
+- **connector:** [Forte] Response Handling for Verify Action ([#2601](https://github.com/juspay/hyperswitch/pull/2601)) ([`efed596`](https://github.com/juspay/hyperswitch/commit/efed5968236a8ae3b26a7697e4972f243add4292))
+
+### Refactors
+
+- **connector:**
+  - [Airwallex] Remove default case handling ([#2703](https://github.com/juspay/hyperswitch/pull/2703)) ([`4138c8f`](https://github.com/juspay/hyperswitch/commit/4138c8f5431dea4fe400b47c919c68b7c8f7b402))
+  - Use connector_request_reference_id for Fiserv ([#2698](https://github.com/juspay/hyperswitch/pull/2698)) ([`05c2f84`](https://github.com/juspay/hyperswitch/commit/05c2f842e3b9c579f611716b08a10766a6d13a30))
+  - [Rapyd] add and implement the get_currency_unit function ([#2664](https://github.com/juspay/hyperswitch/pull/2664)) ([`78e5cd0`](https://github.com/juspay/hyperswitch/commit/78e5cd00b55ad2bd25083aecceaa8762efe3b48d))
+  - [Square] remove default case handling ([#2701](https://github.com/juspay/hyperswitch/pull/2701)) ([`05100ea`](https://github.com/juspay/hyperswitch/commit/05100ea38d540d17e211e06ea99fcfeae7958975))
+  - Use connector_request_reference_id for Iatapay ([#2692](https://github.com/juspay/hyperswitch/pull/2692)) ([`4afe552`](https://github.com/juspay/hyperswitch/commit/4afe552563c6a0cb9544a9a2f870bb9d07d7cf18))
+
+### Testing
+
+- **postman:** Update postman collection files ([`8eca66a`](https://github.com/juspay/hyperswitch/commit/8eca66a2eb8770783c671b299765aa15d7fa72f8))
+
+### Documentation
+
+- **changelog:** Fix typo in changelog ([#2713](https://github.com/juspay/hyperswitch/pull/2713)) ([`2815443`](https://github.com/juspay/hyperswitch/commit/2815443c1b147e005a2384ff817292b1845a9f88))
+
+**Full Changelog:** [`v1.67.0...v1.68.0`](https://github.com/juspay/hyperswitch/compare/v1.67.0...v1.68.0)
+
+- - -
+
+
+## 1.67.0 (2023-10-26)
+
+### Features
+
+- **connector:** [OpenNode] Use connector_request_reference_id as reference to connector ([#2596](https://github.com/juspay/hyperswitch/pull/2596)) ([`96b790c`](https://github.com/juspay/hyperswitch/commit/96b790cb4b44cd4867be62e2889cb4aa23622161))
+
+### Bug Fixes
+
+- **connector:** [Paypal]fix paypal error reason mapping when it is empty string. ([#2700](https://github.com/juspay/hyperswitch/pull/2700)) ([`2c00767`](https://github.com/juspay/hyperswitch/commit/2c007675aec13b0696c74568af36eea2c799d9ef))
+
+### Refactors
+
+- **connector:**
+  - [Worldpay] Remove Default Case Handling ([#2488](https://github.com/juspay/hyperswitch/pull/2488)) ([`2b2c381`](https://github.com/juspay/hyperswitch/commit/2b2c38146dc6dcf8d967dcc557281d3689bf746b))
+  - Added default case for Opayo ([#2687](https://github.com/juspay/hyperswitch/pull/2687)) ([`1186f8c`](https://github.com/juspay/hyperswitch/commit/1186f8c4e2f04f470f4d6c058c18cd63f35b3804))
+- **router:** Tsys default case handling ([#2672](https://github.com/juspay/hyperswitch/pull/2672)) ([`9ff2721`](https://github.com/juspay/hyperswitch/commit/9ff272121a4b6d8d5e1565863d7f13caf06785b1))
+
+### Testing
+
+- **postman:** Update postman collection files ([`9875687`](https://github.com/juspay/hyperswitch/commit/9875687e044a3b5f916fd65b9e457caec7f4e0f6))
+
+### Build System / Dependencies
+
+- **docker:** Copy over `.gitignore` as `.dockerignore` ([#2691](https://github.com/juspay/hyperswitch/pull/2691)) ([`d680eb2`](https://github.com/juspay/hyperswitch/commit/d680eb2b49f85795daafdda9caa0fd3fe6db8108))
+
+**Full Changelog:** [`v1.66.0...v1.67.0`](https://github.com/juspay/hyperswitch/compare/v1.66.0...v1.67.0)
+
+- - -
+
+
+## 1.66.0 (2023-10-25)
+
+### Features
+
+- **core:** Add support for multiple `merchant_connector_account`  ([#2655](https://github.com/juspay/hyperswitch/pull/2655)) ([`5988d8d`](https://github.com/juspay/hyperswitch/commit/5988d8d42605af006fdf7d7821bbdf66e4468669))
+
+**Full Changelog:** [`v1.65.0...v1.66.0`](https://github.com/juspay/hyperswitch/compare/v1.65.0...v1.66.0)
+
+- - -
+
+
+## 1.65.0 (2023-10-25)
+
+### Features
+
+- **router_env:** Add support for UUID v7 for tracing actix web ([#2661](https://github.com/juspay/hyperswitch/pull/2661)) ([`65319fe`](https://github.com/juspay/hyperswitch/commit/65319fe958aaf88e48e06f731ffae8273f7b586c))
+
+### Bug Fixes
+
+- **core:** Address clippy config changes ([#2654](https://github.com/juspay/hyperswitch/pull/2654)) ([`cfe9c25`](https://github.com/juspay/hyperswitch/commit/cfe9c2529e3c16f4d43df37f6357c70f7ca39aa6))
+- **refunds:**
+  - Add `profile_id` in refunds response ([#2652](https://github.com/juspay/hyperswitch/pull/2652)) ([`bb86cc2`](https://github.com/juspay/hyperswitch/commit/bb86cc2d04665ccd68eebea68a3d5b58f481c63d))
+  - Fetch refund if insert fails due to duplicate response ([#2682](https://github.com/juspay/hyperswitch/pull/2682)) ([`433cdfa`](https://github.com/juspay/hyperswitch/commit/433cdfa296849a9e642eb574bf79ee1b03b89ff6))
+
+### Refactors
+
+- **connector:**
+  - [CryptoPay] Remove Default Case Handling ([#2643](https://github.com/juspay/hyperswitch/pull/2643)) ([`6428d07`](https://github.com/juspay/hyperswitch/commit/6428d07f983026245159de4147b62bc0fc018165))
+  - [CyberSource] Enhance currency Mapping with ConnectorCurrencyCommon Trait ([#2626](https://github.com/juspay/hyperswitch/pull/2626)) ([`f2f8170`](https://github.com/juspay/hyperswitch/commit/f2f8170ae1bcc2167f5bc2dfcc58f0c9f1ea0160))
+  - [Cryptopay] add psync reference id validation for Cryptopay ([#2668](https://github.com/juspay/hyperswitch/pull/2668)) ([`27b9762`](https://github.com/juspay/hyperswitch/commit/27b97626245cab12dd9aefb4d85a77b5c913dba0))
+  - Default case for worldline ([#2674](https://github.com/juspay/hyperswitch/pull/2674)) ([`e6272c6`](https://github.com/juspay/hyperswitch/commit/e6272c6418e5dbf9af94c48ef8814d5f415de793))
+
+### Testing
+
+- **postman:** Update postman collection files ([`b340673`](https://github.com/juspay/hyperswitch/commit/b34067312ee7a5bc3c1498a1ff06e52849c90081))
+
+**Full Changelog:** [`v1.64.1...v1.65.0`](https://github.com/juspay/hyperswitch/compare/v1.64.1...v1.65.0)
+
+- - -
+
+
+## 1.64.1 (2023-10-24)
+
+### Refactors
+
+- Revert redis temp locker logic ([#2670](https://github.com/juspay/hyperswitch/pull/2670)) ([`eaa9720`](https://github.com/juspay/hyperswitch/commit/eaa972052024678ade122eec14261f9f33788e45))
+
+**Full Changelog:** [`v1.64.0...v1.64.1`](https://github.com/juspay/hyperswitch/compare/v1.64.0...v1.64.1)
+
+- - -
+
+
+## 1.64.0 (2023-10-23)
+
+### Features
+
+- **events:** Add request body to api events logger ([#2660](https://github.com/juspay/hyperswitch/pull/2660)) ([`830eee9`](https://github.com/juspay/hyperswitch/commit/830eee94e1d35dcd14ef9989eb7b6003c1244a18))
+
+### Bug Fixes
+
+- **router:** Disable openapi examples ([#2648](https://github.com/juspay/hyperswitch/pull/2648)) ([`b39bdbf`](https://github.com/juspay/hyperswitch/commit/b39bdbf0c24730fea9cde0dcfa07ac43e4dd69a4))
+
+### Refactors
+
+- **connector:**
+  - Use connector_response_reference_id  for Shift4 ([#2492](https://github.com/juspay/hyperswitch/pull/2492)) ([`83f0062`](https://github.com/juspay/hyperswitch/commit/83f0062aad9886a5a0c4ecff7412acfec63f7423))
+  - [PowerTranz] refactor powertranz payments to remove default cases ([#2547](https://github.com/juspay/hyperswitch/pull/2547)) ([`664093d`](https://github.com/juspay/hyperswitch/commit/664093dc79743203196d912c17570885718b1c02))
+
+**Full Changelog:** [`v1.63.0...v1.64.0`](https://github.com/juspay/hyperswitch/compare/v1.63.0...v1.64.0)
+
+- - -
+
+
+## 1.63.0 (2023-10-20)
+
+### Features
+
+- Add support for updating surcharge_applicable field intent ([#2647](https://github.com/juspay/hyperswitch/pull/2647)) ([`949937e`](https://github.com/juspay/hyperswitch/commit/949937e3644346f8b2b952944efb884f270645a8))
+
+### Bug Fixes
+
+- Kms decryption of redis_temp_locker_encryption_key ([#2650](https://github.com/juspay/hyperswitch/pull/2650)) ([`5a6601f`](https://github.com/juspay/hyperswitch/commit/5a6601fad4d11cd7d2f1322a6453504494d20c6f))
+
+### Refactors
+
+- **router:** [Nexi nets] Remove Default Case Handling ([#2639](https://github.com/juspay/hyperswitch/pull/2639)) ([`4b64c56`](https://github.com/juspay/hyperswitch/commit/4b64c563558d7c0a02b248c23921ed47ff294980))
+
+**Full Changelog:** [`v1.62.0...v1.63.0`](https://github.com/juspay/hyperswitch/compare/v1.62.0...v1.63.0)
+
+- - -
+
+
+## 1.62.0 (2023-10-19)
+
+### Features
+
+- **connector:**
+  - [Worldpay] Use connector_request_reference_id as reference to the connector ([#2553](https://github.com/juspay/hyperswitch/pull/2553)) ([`9ea5830`](https://github.com/juspay/hyperswitch/commit/9ea5830befe333270f8f424753e1b46a439e79bb))
+  - [ProphetPay] Template generation ([#2610](https://github.com/juspay/hyperswitch/pull/2610)) ([`7e6207e`](https://github.com/juspay/hyperswitch/commit/7e6207e6ca98fe2af9a61e272735e9d2292d6a92))
+  - [Bambora] Use connector_response_reference_id as reference to the connector ([#2635](https://github.com/juspay/hyperswitch/pull/2635)) ([`a9b5dc9`](https://github.com/juspay/hyperswitch/commit/a9b5dc9ab767eb54a95bcebc4fd5a7b00dbf65f6))
+  - [Klarna] Add order id as the reference id to merchant ([#2614](https://github.com/juspay/hyperswitch/pull/2614)) ([`b7d5573`](https://github.com/juspay/hyperswitch/commit/b7d557367a3a5aca478ffd2087af8077bc4e7e2b))
+
+### Bug Fixes
+
+- Payment_method_data and description null during payment confirm ([#2618](https://github.com/juspay/hyperswitch/pull/2618)) ([`6765a1c`](https://github.com/juspay/hyperswitch/commit/6765a1c695493499d1907c56d05bdcd80a2fea93))
+
+### Refactors
+
+- **connector:**
+  - [Dlocal] Currency Unit Conversion ([#2615](https://github.com/juspay/hyperswitch/pull/2615)) ([`1f2fe51`](https://github.com/juspay/hyperswitch/commit/1f2fe5170ae318a8b1613f6f02538a36f30f0b3d))
+  - [Iatapay] remove default case handling ([#2587](https://github.com/juspay/hyperswitch/pull/2587)) ([`6494e8a`](https://github.com/juspay/hyperswitch/commit/6494e8a6e4a195ecc9ca5b2f6ac0a636f06b03f7))
+  - [noon] remove cancellation_reason ([#2627](https://github.com/juspay/hyperswitch/pull/2627)) ([`41b7742`](https://github.com/juspay/hyperswitch/commit/41b7742b5498bfa9ef32b9408ab2d9a7a43b01dc))
+  - [Forte] Remove Default Case Handling ([#2625](https://github.com/juspay/hyperswitch/pull/2625)) ([`418715b`](https://github.com/juspay/hyperswitch/commit/418715b816337bcaeee1aceeb911e6d329add2ad))
+  - [Dlocal] remove default case handling ([#2624](https://github.com/juspay/hyperswitch/pull/2624)) ([`1584313`](https://github.com/juspay/hyperswitch/commit/158431391d560be4a79160ccea7bf5feaa4b52db))
+- Remove code related to temp locker ([#2640](https://github.com/juspay/hyperswitch/pull/2640)) ([`cc0b422`](https://github.com/juspay/hyperswitch/commit/cc0b42263257b6cf6c7f94350442a74d3c02750b))
+- Add surcharge_applicable to payment_intent and remove surcharge_metadata from payment_attempt ([#2642](https://github.com/juspay/hyperswitch/pull/2642)) ([`e5fbaae`](https://github.com/juspay/hyperswitch/commit/e5fbaae0d4278681e5f589aa46c867e7904c4646))
+
+### Testing
+
+- **postman:** Update postman collection files ([`2593dd1`](https://github.com/juspay/hyperswitch/commit/2593dd17c30d7f327b54f3c386a9fd42ae8146ca))
+
+### Miscellaneous Tasks
+
+- **deps:** Bump rustix from 0.37.24 to 0.37.25 ([#2637](https://github.com/juspay/hyperswitch/pull/2637)) ([`67d0062`](https://github.com/juspay/hyperswitch/commit/67d006272158372a4b9ec65cbbe7b2ae8f35eb69))
+
+### Build System / Dependencies
+
+- **deps:** Use `async-bb8-diesel` from `crates.io` instead of git repository ([#2619](https://github.com/juspay/hyperswitch/pull/2619)) ([`14c0821`](https://github.com/juspay/hyperswitch/commit/14c0821b8085279072db3484a3b1bcdde0f7893b))
+
+**Full Changelog:** [`v1.61.0...v1.62.0`](https://github.com/juspay/hyperswitch/compare/v1.61.0...v1.62.0)
+
+- - -
+
+
 ## 1.61.0 (2023-10-18)
 
 ### Features
diff --git a/Cargo.lock b/Cargo.lock
index 66bace95e7a3..a03340093c88 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,30 +2,6 @@
 # It is not intended for manual editing.
 version = 3
 
-[[package]]
-name = "actix"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f728064aca1c318585bf4bb04ffcfac9e75e508ab4e8b1bd9ba5dfe04e2cbed5"
-dependencies = [
- "actix-rt",
- "actix_derive",
- "bitflags 1.3.2",
- "bytes",
- "crossbeam-channel",
- "futures-core",
- "futures-sink",
- "futures-task",
- "futures-util",
- "log",
- "once_cell",
- "parking_lot",
- "pin-project-lite",
- "smallvec",
- "tokio",
- "tokio-util",
-]
-
 [[package]]
 name = "actix-codec"
 version = "0.5.1"
@@ -33,12 +9,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8"
 dependencies = [
  "bitflags 1.3.2",
- "bytes",
+ "bytes 1.5.0",
  "futures-core",
  "futures-sink",
  "memchr",
  "pin-project-lite",
- "tokio",
+ "tokio 1.32.0",
  "tokio-util",
  "tracing",
 ]
@@ -55,7 +31,7 @@ dependencies = [
  "futures-util",
  "log",
  "once_cell",
- "smallvec",
+ "smallvec 1.11.1",
 ]
 
 [[package]]
@@ -72,7 +48,7 @@ dependencies = [
  "base64 0.21.4",
  "bitflags 1.3.2",
  "brotli",
- "bytes",
+ "bytes 1.5.0",
  "bytestring",
  "derive_more",
  "encoding_rs",
@@ -90,8 +66,8 @@ dependencies = [
  "pin-project-lite",
  "rand 0.8.5",
  "sha1",
- "smallvec",
- "tokio",
+ "smallvec 1.11.1",
+ "tokio 1.32.0",
  "tokio-util",
  "tracing",
  "zstd",
@@ -116,7 +92,7 @@ dependencies = [
  "actix-multipart-derive",
  "actix-utils",
  "actix-web",
- "bytes",
+ "bytes 1.5.0",
  "derive_more",
  "futures-core",
  "futures-util",
@@ -129,7 +105,7 @@ dependencies = [
  "serde_json",
  "serde_plain",
  "tempfile",
- "tokio",
+ "tokio 1.32.0",
 ]
 
 [[package]]
@@ -166,7 +142,7 @@ checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d"
 dependencies = [
  "actix-macros",
  "futures-core",
- "tokio",
+ "tokio 1.32.0",
 ]
 
 [[package]]
@@ -180,9 +156,9 @@ dependencies = [
  "actix-utils",
  "futures-core",
  "futures-util",
- "mio",
+ "mio 0.8.8",
  "socket2 0.5.4",
- "tokio",
+ "tokio 1.32.0",
  "tracing",
 ]
 
@@ -212,7 +188,7 @@ dependencies = [
  "pin-project-lite",
  "rustls 0.21.7",
  "rustls-webpki",
- "tokio",
+ "tokio 1.32.0",
  "tokio-rustls",
  "tokio-util",
  "tracing",
@@ -245,9 +221,9 @@ dependencies = [
  "actix-utils",
  "actix-web-codegen",
  "ahash 0.7.6",
- "bytes",
+ "bytes 1.5.0",
  "bytestring",
- "cfg-if",
+ "cfg-if 1.0.0",
  "cookie",
  "derive_more",
  "encoding_rs",
@@ -264,7 +240,7 @@ dependencies = [
  "serde",
  "serde_json",
  "serde_urlencoded",
- "smallvec",
+ "smallvec 1.11.1",
  "socket2 0.4.9",
  "time",
  "url",
@@ -282,17 +258,6 @@ dependencies = [
  "syn 2.0.38",
 ]
 
-[[package]]
-name = "actix_derive"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d44b8fee1ced9671ba043476deddef739dd0959bf77030b26b738cc591737a7"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
 [[package]]
 name = "addr2line"
 version = "0.21.0"
@@ -331,7 +296,7 @@ version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "getrandom 0.2.10",
  "once_cell",
  "version_check",
@@ -361,6 +326,12 @@ dependencies = [
  "alloc-no-stdlib",
 ]
 
+[[package]]
+name = "allocator-api2"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
+
 [[package]]
 name = "android-tzdata"
 version = "0.1.1"
@@ -376,6 +347,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "anes"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
+
 [[package]]
 name = "anstyle"
 version = "1.0.0"
@@ -397,15 +374,14 @@ dependencies = [
  "common_enums",
  "common_utils",
  "error-stack",
+ "euclid",
  "masking",
  "mime",
  "reqwest",
  "router_derive",
  "serde",
  "serde_json",
- "serde_with",
  "strum 0.24.1",
- "thiserror",
  "time",
  "url",
  "utoipa",
@@ -423,6 +399,18 @@ version = "1.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3f907281554a3d0312bb7aab855a8e0ef6cbf1614d06de54105039ca8b34460e"
 
+[[package]]
+name = "argon2"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17ba4cac0a46bc1d2912652a751c47f2a9f3a7fe89bcae2275d418f5270402f9"
+dependencies = [
+ "base64ct",
+ "blake2",
+ "cpufeatures",
+ "password-hash",
+]
+
 [[package]]
 name = "arrayref"
 version = "0.3.7"
@@ -487,14 +475,14 @@ dependencies = [
 [[package]]
 name = "async-bb8-diesel"
 version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "779f1fa3defe66bf147fe5c811b23a02cfcaa528a25293e0b20d1911eac1fb05"
+source = "git+https://github.com/jarnura/async-bb8-diesel?rev=53b4ab901aab7635c8215fd1c2d542c8db443094#53b4ab901aab7635c8215fd1c2d542c8db443094"
 dependencies = [
  "async-trait",
  "bb8",
  "diesel",
  "thiserror",
- "tokio",
+ "tokio 1.32.0",
+ "tracing",
 ]
 
 [[package]]
@@ -518,7 +506,7 @@ dependencies = [
  "futures-core",
  "memchr",
  "pin-project-lite",
- "tokio",
+ "tokio 1.32.0",
 ]
 
 [[package]]
@@ -529,7 +517,7 @@ checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
 dependencies = [
  "async-lock",
  "autocfg",
- "cfg-if",
+ "cfg-if 1.0.0",
  "concurrent-queue",
  "futures-lite",
  "log",
@@ -583,6 +571,21 @@ dependencies = [
  "syn 2.0.38",
 ]
 
+[[package]]
+name = "atoi"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "atomic"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba"
+
 [[package]]
 name = "autocfg"
 version = "1.1.0"
@@ -603,8 +606,8 @@ dependencies = [
  "actix-utils",
  "ahash 0.7.6",
  "base64 0.21.4",
- "bytes",
- "cfg-if",
+ "bytes 1.5.0",
+ "cfg-if 1.0.0",
  "cookie",
  "derive_more",
  "futures-core",
@@ -621,7 +624,7 @@ dependencies = [
  "serde",
  "serde_json",
  "serde_urlencoded",
- "tokio",
+ "tokio 1.32.0",
 ]
 
 [[package]]
@@ -641,14 +644,14 @@ dependencies = [
  "aws-smithy-json",
  "aws-smithy-types",
  "aws-types",
- "bytes",
+ "bytes 1.5.0",
  "fastrand 1.9.0",
  "hex",
  "http",
  "hyper",
  "ring",
  "time",
- "tokio",
+ "tokio 1.32.0",
  "tower",
  "tracing",
  "zeroize",
@@ -663,7 +666,7 @@ dependencies = [
  "aws-smithy-async",
  "aws-smithy-types",
  "fastrand 1.9.0",
- "tokio",
+ "tokio 1.32.0",
  "tracing",
  "zeroize",
 ]
@@ -692,7 +695,7 @@ dependencies = [
  "aws-smithy-http",
  "aws-smithy-types",
  "aws-types",
- "bytes",
+ "bytes 1.5.0",
  "http",
  "http-body",
  "lazy_static",
@@ -718,7 +721,7 @@ dependencies = [
  "aws-smithy-json",
  "aws-smithy-types",
  "aws-types",
- "bytes",
+ "bytes 1.5.0",
  "http",
  "regex",
  "tokio-stream",
@@ -747,7 +750,7 @@ dependencies = [
  "aws-smithy-types",
  "aws-smithy-xml",
  "aws-types",
- "bytes",
+ "bytes 1.5.0",
  "http",
  "http-body",
  "once_cell",
@@ -776,7 +779,7 @@ dependencies = [
  "aws-smithy-json",
  "aws-smithy-types",
  "aws-types",
- "bytes",
+ "bytes 1.5.0",
  "http",
  "regex",
  "tokio-stream",
@@ -801,7 +804,7 @@ dependencies = [
  "aws-smithy-json",
  "aws-smithy-types",
  "aws-types",
- "bytes",
+ "bytes 1.5.0",
  "http",
  "regex",
  "tokio-stream",
@@ -828,7 +831,7 @@ dependencies = [
  "aws-smithy-types",
  "aws-smithy-xml",
  "aws-types",
- "bytes",
+ "bytes 1.5.0",
  "http",
  "regex",
  "tower",
@@ -858,7 +861,7 @@ checksum = "9d2ce6f507be68e968a33485ced670111d1cbad161ddbbab1e313c03d37d8f4c"
 dependencies = [
  "aws-smithy-eventstream",
  "aws-smithy-http",
- "bytes",
+ "bytes 1.5.0",
  "form_urlencoded",
  "hex",
  "hmac",
@@ -879,7 +882,7 @@ checksum = "13bda3996044c202d75b91afeb11a9afae9db9a721c6a7a427410018e286b880"
 dependencies = [
  "futures-util",
  "pin-project-lite",
- "tokio",
+ "tokio 1.32.0",
  "tokio-stream",
 ]
 
@@ -891,7 +894,7 @@ checksum = "07ed8b96d95402f3f6b8b57eb4e0e45ee365f78b1a924faf20ff6e97abf1eae6"
 dependencies = [
  "aws-smithy-http",
  "aws-smithy-types",
- "bytes",
+ "bytes 1.5.0",
  "crc32c",
  "crc32fast",
  "hex",
@@ -914,7 +917,7 @@ dependencies = [
  "aws-smithy-http",
  "aws-smithy-http-tower",
  "aws-smithy-types",
- "bytes",
+ "bytes 1.5.0",
  "fastrand 1.9.0",
  "http",
  "http-body",
@@ -923,7 +926,7 @@ dependencies = [
  "lazy_static",
  "pin-project-lite",
  "rustls 0.20.9",
- "tokio",
+ "tokio 1.32.0",
  "tower",
  "tracing",
 ]
@@ -935,7 +938,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "460c8da5110835e3d9a717c61f5556b20d03c32a1dec57f8fc559b360f733bb8"
 dependencies = [
  "aws-smithy-types",
- "bytes",
+ "bytes 1.5.0",
  "crc32fast",
 ]
 
@@ -947,7 +950,7 @@ checksum = "2b3b693869133551f135e1f2c77cb0b8277d9e3e17feaf2213f735857c4f0d28"
 dependencies = [
  "aws-smithy-eventstream",
  "aws-smithy-types",
- "bytes",
+ "bytes 1.5.0",
  "bytes-utils",
  "futures-core",
  "http",
@@ -957,7 +960,7 @@ dependencies = [
  "percent-encoding",
  "pin-project-lite",
  "pin-utils",
- "tokio",
+ "tokio 1.32.0",
  "tokio-util",
  "tracing",
 ]
@@ -970,7 +973,7 @@ checksum = "3ae4f6c5798a247fac98a867698197d9ac22643596dc3777f0c76b91917616b9"
 dependencies = [
  "aws-smithy-http",
  "aws-smithy-types",
- "bytes",
+ "bytes 1.5.0",
  "http",
  "http-body",
  "pin-project-lite",
@@ -1031,7 +1034,7 @@ dependencies = [
  "aws-smithy-http",
  "aws-smithy-types",
  "http",
- "rustc_version",
+ "rustc_version 0.4.0",
  "tracing",
 ]
 
@@ -1044,7 +1047,7 @@ dependencies = [
  "async-trait",
  "axum-core",
  "bitflags 1.3.2",
- "bytes",
+ "bytes 1.5.0",
  "futures-util",
  "http",
  "http-body",
@@ -1070,7 +1073,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
 dependencies = [
  "async-trait",
- "bytes",
+ "bytes 1.5.0",
  "futures-util",
  "http",
  "http-body",
@@ -1088,7 +1091,7 @@ checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
 dependencies = [
  "addr2line",
  "cc",
- "cfg-if",
+ "cfg-if 1.0.0",
  "libc",
  "miniz_oxide 0.7.1",
  "object",
@@ -1117,6 +1120,12 @@ dependencies = [
  "vsimd",
 ]
 
+[[package]]
+name = "base64ct"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
+
 [[package]]
 name = "bb8"
 version = "0.8.1"
@@ -1126,8 +1135,19 @@ dependencies = [
  "async-trait",
  "futures-channel",
  "futures-util",
- "parking_lot",
- "tokio",
+ "parking_lot 0.12.1",
+ "tokio 1.32.0",
+]
+
+[[package]]
+name = "bigdecimal"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa"
+dependencies = [
+ "num-bigint",
+ "num-integer",
+ "num-traits",
 ]
 
 [[package]]
@@ -1166,6 +1186,15 @@ version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
 
+[[package]]
+name = "blake2"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
+dependencies = [
+ "digest 0.10.7",
+]
+
 [[package]]
 name = "blake3"
 version = "1.4.0"
@@ -1175,7 +1204,7 @@ dependencies = [
  "arrayref",
  "arrayvec",
  "cc",
- "cfg-if",
+ "cfg-if 1.0.0",
  "constant_time_eq",
  "digest 0.10.7",
 ]
@@ -1253,6 +1282,16 @@ version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
+[[package]]
+name = "bytes"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
+dependencies = [
+ "byteorder",
+ "iovec",
+]
+
 [[package]]
 name = "bytes"
 version = "1.5.0"
@@ -1265,7 +1304,7 @@ version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e47d3a8076e283f3acd27400535992edb3ba4b5bb72f8891ad8fbe7932a7d4b9"
 dependencies = [
- "bytes",
+ "bytes 1.5.0",
  "either",
 ]
 
@@ -1275,7 +1314,7 @@ version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "238e4886760d98c4f899360c834fa93e62cf7f721ac3c2da375cbdf4b8679aae"
 dependencies = [
- "bytes",
+ "bytes 1.5.0",
 ]
 
 [[package]]
@@ -1318,7 +1357,7 @@ checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
 dependencies = [
  "camino",
  "cargo-platform",
- "semver",
+ "semver 1.0.19",
  "serde",
  "serde_json",
 ]
@@ -1331,12 +1370,18 @@ checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a"
 dependencies = [
  "camino",
  "cargo-platform",
- "semver",
+ "semver 1.0.19",
  "serde",
  "serde_json",
  "thiserror",
 ]
 
+[[package]]
+name = "cast"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
+
 [[package]]
 name = "cc"
 version = "1.0.83"
@@ -1358,6 +1403,12 @@ dependencies = [
  "uuid",
 ]
 
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+
 [[package]]
 name = "cfg-if"
 version = "1.0.0"
@@ -1407,6 +1458,33 @@ dependencies = [
  "phf_codegen",
 ]
 
+[[package]]
+name = "ciborium"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926"
+dependencies = [
+ "ciborium-io",
+ "ciborium-ll",
+ "serde",
+]
+
+[[package]]
+name = "ciborium-io"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656"
+
+[[package]]
+name = "ciborium-ll"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b"
+dependencies = [
+ "ciborium-io",
+ "half",
+]
+
 [[package]]
 name = "clap"
 version = "4.3.4"
@@ -1447,6 +1525,15 @@ version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
 
+[[package]]
+name = "cloudabi"
+version = "0.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
 [[package]]
 name = "color_quant"
 version = "1.1.0"
@@ -1457,13 +1544,11 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
 name = "common_enums"
 version = "0.1.0"
 dependencies = [
- "common_utils",
  "diesel",
  "router_derive",
  "serde",
  "serde_json",
  "strum 0.25.0",
- "time",
  "utoipa",
 ]
 
@@ -1472,11 +1557,12 @@ name = "common_utils"
 version = "0.1.0"
 dependencies = [
  "async-trait",
- "bytes",
+ "bytes 1.5.0",
+ "common_enums",
  "diesel",
  "error-stack",
  "fake",
- "futures",
+ "futures 0.3.28",
  "hex",
  "http",
  "masking",
@@ -1491,6 +1577,7 @@ dependencies = [
  "reqwest",
  "ring",
  "router_env",
+ "rustc-hash",
  "serde",
  "serde_json",
  "serde_urlencoded",
@@ -1500,7 +1587,7 @@ dependencies = [
  "test-case",
  "thiserror",
  "time",
- "tokio",
+ "tokio 1.32.0",
 ]
 
 [[package]]
@@ -1509,7 +1596,7 @@ version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400"
 dependencies = [
- "crossbeam-utils",
+ "crossbeam-utils 0.8.16",
 ]
 
 [[package]]
@@ -1585,6 +1672,21 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "crc"
+version = "3.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe"
+dependencies = [
+ "crc-catalog",
+]
+
+[[package]]
+name = "crc-catalog"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
+
 [[package]]
 name = "crc16"
 version = "0.4.0"
@@ -1597,7 +1699,7 @@ version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d8f48d60e5b4d2c53d5c2b1d8a58c849a70ae5e5509b08a48d047e3b65714a74"
 dependencies = [
- "rustc_version",
+ "rustc_version 0.4.0",
 ]
 
 [[package]]
@@ -1606,7 +1708,43 @@ version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
+]
+
+[[package]]
+name = "criterion"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
+dependencies = [
+ "anes",
+ "cast",
+ "ciborium",
+ "clap",
+ "criterion-plot",
+ "is-terminal",
+ "itertools 0.10.5",
+ "num-traits",
+ "once_cell",
+ "oorandom",
+ "plotters",
+ "rayon",
+ "regex",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "tinytemplate",
+ "walkdir",
+]
+
+[[package]]
+name = "criterion-plot"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
+dependencies = [
+ "cast",
+ "itertools 0.10.5",
 ]
 
 [[package]]
@@ -1615,8 +1753,19 @@ version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
 dependencies = [
- "cfg-if",
- "crossbeam-utils",
+ "cfg-if 1.0.0",
+ "crossbeam-utils 0.8.16",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed"
+dependencies = [
+ "crossbeam-epoch 0.8.2",
+ "crossbeam-utils 0.7.2",
+ "maybe-uninit",
 ]
 
 [[package]]
@@ -1625,9 +1774,24 @@ version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
 dependencies = [
- "cfg-if",
- "crossbeam-epoch",
- "crossbeam-utils",
+ "cfg-if 1.0.0",
+ "crossbeam-epoch 0.9.15",
+ "crossbeam-utils 0.8.16",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
+dependencies = [
+ "autocfg",
+ "cfg-if 0.1.10",
+ "crossbeam-utils 0.7.2",
+ "lazy_static",
+ "maybe-uninit",
+ "memoffset 0.5.6",
+ "scopeguard",
 ]
 
 [[package]]
@@ -1637,19 +1801,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
 dependencies = [
  "autocfg",
- "cfg-if",
- "crossbeam-utils",
- "memoffset",
+ "cfg-if 1.0.0",
+ "crossbeam-utils 0.8.16",
+ "memoffset 0.9.0",
  "scopeguard",
 ]
 
+[[package]]
+name = "crossbeam-queue"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570"
+dependencies = [
+ "cfg-if 0.1.10",
+ "crossbeam-utils 0.7.2",
+ "maybe-uninit",
+]
+
+[[package]]
+name = "crossbeam-queue"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
+dependencies = [
+ "cfg-if 1.0.0",
+ "crossbeam-utils 0.8.16",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
+dependencies = [
+ "autocfg",
+ "cfg-if 0.1.10",
+ "lazy_static",
+]
+
 [[package]]
 name = "crossbeam-utils"
 version = "0.8.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
 ]
 
 [[package]]
@@ -1738,11 +1934,11 @@ version = "5.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "hashbrown 0.14.1",
- "lock_api",
+ "lock_api 0.4.10",
  "once_cell",
- "parking_lot_core",
+ "parking_lot_core 0.9.8",
 ]
 
 [[package]]
@@ -1763,7 +1959,6 @@ dependencies = [
  "masking",
  "serde",
  "serde_json",
- "strum 0.25.0",
  "thiserror",
  "time",
 ]
@@ -1778,7 +1973,7 @@ dependencies = [
  "deadpool-runtime",
  "num_cpus",
  "retain_mut",
- "tokio",
+ "tokio 1.32.0",
 ]
 
 [[package]]
@@ -1831,7 +2026,7 @@ dependencies = [
  "convert_case",
  "proc-macro2",
  "quote",
- "rustc_version",
+ "rustc_version 0.4.0",
  "syn 1.0.109",
 ]
 
@@ -1874,13 +2069,10 @@ name = "diesel_models"
 version = "0.1.0"
 dependencies = [
  "async-bb8-diesel",
- "aws-config",
- "aws-sdk-s3",
  "common_enums",
  "common_utils",
  "diesel",
  "error-stack",
- "external_services",
  "frunk",
  "frunk_core",
  "masking",
@@ -1945,7 +2137,7 @@ checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
 dependencies = [
  "libc",
  "redox_users",
- "winapi",
+ "winapi 0.3.9",
 ]
 
 [[package]]
@@ -1965,6 +2157,12 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
 
+[[package]]
+name = "dotenvy"
+version = "0.15.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
+
 [[package]]
 name = "drainer"
 version = "0.1.0"
@@ -1986,7 +2184,7 @@ dependencies = [
  "serde_json",
  "serde_path_to_error",
  "thiserror",
- "tokio",
+ "tokio 1.32.0",
 ]
 
 [[package]]
@@ -2007,7 +2205,7 @@ version = "0.8.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
 ]
 
 [[package]]
@@ -2016,6 +2214,15 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
 
+[[package]]
+name = "erased-serde"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c"
+dependencies = [
+ "serde",
+]
+
 [[package]]
 name = "errno"
 version = "0.3.4"
@@ -2053,8 +2260,54 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5f00447f331c7f726db5b8532ebc9163519eed03c6d7c8b73c90b3ff5646ac85"
 dependencies = [
  "anyhow",
- "rustc_version",
+ "rustc_version 0.4.0",
+ "serde",
+]
+
+[[package]]
+name = "euclid"
+version = "0.1.0"
+dependencies = [
+ "common_enums",
+ "criterion",
+ "erased-serde",
+ "euclid_macros",
+ "frunk",
+ "frunk_core",
+ "nom",
+ "once_cell",
+ "rustc-hash",
+ "serde",
+ "serde_json",
+ "strum 0.25.0",
+ "thiserror",
+]
+
+[[package]]
+name = "euclid_macros"
+version = "0.1.0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "rustc-hash",
+ "strum 0.24.1",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "euclid_wasm"
+version = "0.1.0"
+dependencies = [
+ "api_models",
+ "euclid",
+ "getrandom 0.2.10",
+ "kgraph_utils",
+ "once_cell",
+ "ron-parser",
  "serde",
+ "serde-wasm-bindgen",
+ "strum 0.25.0",
+ "wasm-bindgen",
 ]
 
 [[package]]
@@ -2081,7 +2334,7 @@ dependencies = [
  "router_env",
  "serde",
  "thiserror",
- "tokio",
+ "tokio 1.32.0",
 ]
 
 [[package]]
@@ -2111,7 +2364,7 @@ dependencies = [
  "serde",
  "serde_json",
  "time",
- "tokio",
+ "tokio 1.32.0",
  "url",
  "webdriver",
 ]
@@ -2131,6 +2384,12 @@ version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
 
+[[package]]
+name = "finl_unicode"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6"
+
 [[package]]
 name = "flate2"
 version = "1.0.27"
@@ -2189,19 +2448,19 @@ dependencies = [
  "arc-swap",
  "arcstr",
  "async-trait",
- "bytes",
+ "bytes 1.5.0",
  "bytes-utils",
- "cfg-if",
+ "cfg-if 1.0.0",
  "float-cmp",
- "futures",
+ "futures 0.3.28",
  "lazy_static",
  "log",
- "parking_lot",
+ "parking_lot 0.12.1",
  "rand 0.8.5",
  "redis-protocol",
- "semver",
+ "semver 1.0.19",
  "sha-1 0.10.1",
- "tokio",
+ "tokio 1.32.0",
  "tokio-stream",
  "tokio-util",
  "tracing",
@@ -2261,6 +2520,28 @@ dependencies = [
  "syn 2.0.38",
 ]
 
+[[package]]
+name = "fuchsia-zircon"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
+dependencies = [
+ "bitflags 1.3.2",
+ "fuchsia-zircon-sys",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
+
+[[package]]
+name = "futures"
+version = "0.1.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678"
+
 [[package]]
 name = "futures"
 version = "0.3.28"
@@ -2303,6 +2584,17 @@ dependencies = [
  "futures-util",
 ]
 
+[[package]]
+name = "futures-intrusive"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5"
+dependencies = [
+ "futures-core",
+ "lock_api 0.4.10",
+ "parking_lot 0.11.2",
+]
+
 [[package]]
 name = "futures-io"
 version = "0.3.28"
@@ -2397,7 +2689,7 @@ version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "libc",
  "wasi 0.9.0+wasi-snapshot-preview1",
 ]
@@ -2408,9 +2700,11 @@ version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
+ "js-sys",
  "libc",
  "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasm-bindgen",
 ]
 
 [[package]]
@@ -2478,7 +2772,7 @@ version = "0.3.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833"
 dependencies = [
- "bytes",
+ "bytes 1.5.0",
  "fnv",
  "futures-core",
  "futures-sink",
@@ -2486,11 +2780,17 @@ dependencies = [
  "http",
  "indexmap 1.9.3",
  "slab",
- "tokio",
+ "tokio 1.32.0",
  "tokio-util",
  "tracing",
 ]
 
+[[package]]
+name = "half"
+version = "1.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
+
 [[package]]
 name = "hashbrown"
 version = "0.12.3"
@@ -2505,12 +2805,28 @@ name = "hashbrown"
 version = "0.14.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12"
+dependencies = [
+ "ahash 0.8.3",
+ "allocator-api2",
+]
+
+[[package]]
+name = "hashlink"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
+dependencies = [
+ "hashbrown 0.14.1",
+]
 
 [[package]]
 name = "heck"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+dependencies = [
+ "unicode-segmentation",
+]
 
 [[package]]
 name = "hermit-abi"
@@ -2524,6 +2840,15 @@ version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
 
+[[package]]
+name = "hkdf"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
+dependencies = [
+ "hmac",
+]
+
 [[package]]
 name = "hmac"
 version = "0.12.1"
@@ -2539,7 +2864,7 @@ version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
 dependencies = [
- "bytes",
+ "bytes 1.5.0",
  "fnv",
  "itoa",
 ]
@@ -2550,7 +2875,7 @@ version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
 dependencies = [
- "bytes",
+ "bytes 1.5.0",
  "http",
  "pin-project-lite",
 ]
@@ -2603,7 +2928,7 @@ version = "0.14.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
 dependencies = [
- "bytes",
+ "bytes 1.5.0",
  "futures-channel",
  "futures-core",
  "futures-util",
@@ -2615,7 +2940,7 @@ dependencies = [
  "itoa",
  "pin-project-lite",
  "socket2 0.4.9",
- "tokio",
+ "tokio 1.32.0",
  "tower-service",
  "tracing",
  "want",
@@ -2632,7 +2957,7 @@ dependencies = [
  "log",
  "rustls 0.20.9",
  "rustls-native-certs",
- "tokio",
+ "tokio 1.32.0",
  "tokio-rustls",
 ]
 
@@ -2644,7 +2969,7 @@ checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
 dependencies = [
  "hyper",
  "pin-project-lite",
- "tokio",
+ "tokio 1.32.0",
  "tokio-io-timeout",
 ]
 
@@ -2654,10 +2979,10 @@ version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
 dependencies = [
- "bytes",
+ "bytes 1.5.0",
  "hyper",
  "native-tls",
- "tokio",
+ "tokio 1.32.0",
  "tokio-native-tls",
 ]
 
@@ -2785,7 +3110,7 @@ version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
 ]
 
 [[package]]
@@ -2799,12 +3124,32 @@ dependencies = [
  "windows-sys",
 ]
 
+[[package]]
+name = "iovec"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "ipnet"
 version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
 
+[[package]]
+name = "is-terminal"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
+dependencies = [
+ "hermit-abi",
+ "rustix 0.38.17",
+ "windows-sys",
+]
+
 [[package]]
 name = "itertools"
 version = "0.10.5"
@@ -2899,6 +3244,29 @@ dependencies = [
  "simple_asn1",
 ]
 
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+dependencies = [
+ "winapi 0.2.8",
+ "winapi-build",
+]
+
+[[package]]
+name = "kgraph_utils"
+version = "0.1.0"
+dependencies = [
+ "api_models",
+ "criterion",
+ "euclid",
+ "masking",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
 [[package]]
 name = "language-tags"
 version = "0.3.2"
@@ -2975,12 +3343,6 @@ version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db"
 
-[[package]]
-name = "literally"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0d2be3f5a0d4d5c983d1f8ecc2a87676a0875a14feb9eebf0675f7c3e2f3c35"
-
 [[package]]
 name = "local-channel"
 version = "0.1.4"
@@ -2998,6 +3360,15 @@ version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1"
 
+[[package]]
+name = "lock_api"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
+dependencies = [
+ "scopeguard",
+]
+
 [[package]]
 name = "lock_api"
 version = "0.4.10"
@@ -3045,7 +3416,7 @@ dependencies = [
 name = "masking"
 version = "0.1.0"
 dependencies = [
- "bytes",
+ "bytes 1.5.0",
  "diesel",
  "serde",
  "serde_json",
@@ -3092,13 +3463,19 @@ dependencies = [
  "syn 1.0.109",
 ]
 
+[[package]]
+name = "maybe-uninit"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
+
 [[package]]
 name = "md-5"
 version = "0.10.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "digest 0.10.7",
 ]
 
@@ -3114,6 +3491,15 @@ version = "2.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
 
+[[package]]
+name = "memoffset"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa"
+dependencies = [
+ "autocfg",
+]
+
 [[package]]
 name = "memoffset"
 version = "0.9.0"
@@ -3182,6 +3568,25 @@ dependencies = [
  "adler",
 ]
 
+[[package]]
+name = "mio"
+version = "0.6.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
+dependencies = [
+ "cfg-if 0.1.10",
+ "fuchsia-zircon",
+ "fuchsia-zircon-sys",
+ "iovec",
+ "kernel32-sys",
+ "libc",
+ "log",
+ "miow",
+ "net2",
+ "slab",
+ "winapi 0.2.8",
+]
+
 [[package]]
 name = "mio"
 version = "0.8.8"
@@ -3194,6 +3599,29 @@ dependencies = [
  "windows-sys",
 ]
 
+[[package]]
+name = "mio-uds"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
+dependencies = [
+ "iovec",
+ "libc",
+ "mio 0.6.23",
+]
+
+[[package]]
+name = "miow"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
+dependencies = [
+ "kernel32-sys",
+ "net2",
+ "winapi 0.2.8",
+ "ws2_32-sys",
+]
+
 [[package]]
 name = "moka"
 version = "0.11.3"
@@ -3203,16 +3631,16 @@ dependencies = [
  "async-io",
  "async-lock",
  "crossbeam-channel",
- "crossbeam-epoch",
- "crossbeam-utils",
+ "crossbeam-epoch 0.9.15",
+ "crossbeam-utils 0.8.16",
  "futures-util",
  "once_cell",
- "parking_lot",
+ "parking_lot 0.12.1",
  "quanta",
- "rustc_version",
+ "rustc_version 0.4.0",
  "scheduled-thread-pool",
  "skeptic",
- "smallvec",
+ "smallvec 1.11.1",
  "tagptr",
  "thiserror",
  "triomphe",
@@ -3246,6 +3674,17 @@ dependencies = [
  "tempfile",
 ]
 
+[[package]]
+name = "net2"
+version = "0.2.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac"
+dependencies = [
+ "cfg-if 0.1.10",
+ "libc",
+ "winapi 0.3.9",
+]
+
 [[package]]
 name = "nom"
 version = "7.1.3"
@@ -3263,7 +3702,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
 dependencies = [
  "overload",
- "winapi",
+ "winapi 0.3.9",
 ]
 
 [[package]]
@@ -3359,6 +3798,12 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "44d11de466f4a3006fe8a5e7ec84e93b79c70cb992ae0aa0eb631ad2df8abfe2"
 
+[[package]]
+name = "oorandom"
+version = "11.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
+
 [[package]]
 name = "opaque-debug"
 version = "0.3.0"
@@ -3372,7 +3817,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c"
 dependencies = [
  "bitflags 2.4.0",
- "cfg-if",
+ "cfg-if 1.0.0",
  "foreign-types",
  "libc",
  "once_cell",
@@ -3426,14 +3871,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8af72d59a4484654ea8eb183fea5ae4eb6a41d7ac3e3bae5f4d2a282a3a7d3ca"
 dependencies = [
  "async-trait",
- "futures",
+ "futures 0.3.28",
  "futures-util",
  "http",
  "opentelemetry",
  "opentelemetry-proto",
  "prost",
  "thiserror",
- "tokio",
+ "tokio 1.32.0",
  "tonic",
 ]
 
@@ -3443,7 +3888,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "045f8eea8c0fa19f7d48e7bc3128a39c2e5c533d5c61298c548dfefc1064474c"
 dependencies = [
- "futures",
+ "futures 0.3.28",
  "futures-util",
  "opentelemetry",
  "prost",
@@ -3484,7 +3929,7 @@ dependencies = [
  "percent-encoding",
  "rand 0.8.5",
  "thiserror",
- "tokio",
+ "tokio 1.32.0",
  "tokio-stream",
 ]
 
@@ -3516,14 +3961,65 @@ version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067"
 
+[[package]]
+name = "parking_lot"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
+dependencies = [
+ "lock_api 0.3.4",
+ "parking_lot_core 0.6.3",
+ "rustc_version 0.2.3",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api 0.4.10",
+ "parking_lot_core 0.8.6",
+]
+
 [[package]]
 name = "parking_lot"
 version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
 dependencies = [
- "lock_api",
- "parking_lot_core",
+ "lock_api 0.4.10",
+ "parking_lot_core 0.9.8",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bda66b810a62be75176a80873726630147a5ca780cd33921e0b5709033e66b0a"
+dependencies = [
+ "cfg-if 0.1.10",
+ "cloudabi",
+ "libc",
+ "redox_syscall 0.1.57",
+ "rustc_version 0.2.3",
+ "smallvec 0.6.14",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
+dependencies = [
+ "cfg-if 1.0.0",
+ "instant",
+ "libc",
+ "redox_syscall 0.2.16",
+ "smallvec 1.11.1",
+ "winapi 0.3.9",
 ]
 
 [[package]]
@@ -3532,10 +4028,10 @@ version = "0.9.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "libc",
  "redox_syscall 0.3.5",
- "smallvec",
+ "smallvec 1.11.1",
  "windows-targets",
 ]
 
@@ -3554,6 +4050,17 @@ dependencies = [
  "regex",
 ]
 
+[[package]]
+name = "password-hash"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
+dependencies = [
+ "base64ct",
+ "rand_core 0.6.4",
+ "subtle",
+]
+
 [[package]]
 name = "paste"
 version = "1.0.14"
@@ -3723,6 +4230,34 @@ version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
 
+[[package]]
+name = "plotters"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
+dependencies = [
+ "num-traits",
+ "plotters-backend",
+ "plotters-svg",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "plotters-backend"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609"
+
+[[package]]
+name = "plotters-svg"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab"
+dependencies = [
+ "plotters-backend",
+]
+
 [[package]]
 name = "png"
 version = "0.16.8"
@@ -3743,7 +4278,7 @@ checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
 dependencies = [
  "autocfg",
  "bitflags 1.3.2",
- "cfg-if",
+ "cfg-if 1.0.0",
  "concurrent-queue",
  "libc",
  "log",
@@ -3825,7 +4360,7 @@ version = "0.11.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd"
 dependencies = [
- "bytes",
+ "bytes 1.5.0",
  "prost-derive",
 ]
 
@@ -3869,14 +4404,14 @@ version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a17e662a7a8291a865152364c20c7abc5e60486ab2001e8ec10b24862de0b9ab"
 dependencies = [
- "crossbeam-utils",
+ "crossbeam-utils 0.8.16",
  "libc",
  "mach2",
  "once_cell",
  "raw-cpuid",
  "wasi 0.11.0+wasi-snapshot-preview1",
  "web-sys",
- "winapi",
+ "winapi 0.3.9",
 ]
 
 [[package]]
@@ -3911,7 +4446,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93"
 dependencies = [
  "log",
- "parking_lot",
+ "parking_lot 0.12.1",
  "scheduled-thread-pool",
 ]
 
@@ -4020,8 +4555,8 @@ version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
 dependencies = [
- "crossbeam-deque",
- "crossbeam-utils",
+ "crossbeam-deque 0.8.3",
+ "crossbeam-utils 0.8.16",
 ]
 
 [[package]]
@@ -4030,7 +4565,7 @@ version = "4.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c31deddf734dc0a39d3112e73490e88b61a05e83e074d211f348404cee4d2c6"
 dependencies = [
- "bytes",
+ "bytes 1.5.0",
  "bytes-utils",
  "cookie-factory",
  "crc16",
@@ -4045,13 +4580,19 @@ dependencies = [
  "common_utils",
  "error-stack",
  "fred",
- "futures",
+ "futures 0.3.28",
  "router_env",
  "serde",
  "thiserror",
- "tokio",
+ "tokio 1.32.0",
 ]
 
+[[package]]
+name = "redox_syscall"
+version = "0.1.57"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
+
 [[package]]
 name = "redox_syscall"
 version = "0.2.16"
@@ -4145,7 +4686,7 @@ checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
 dependencies = [
  "async-compression",
  "base64 0.21.4",
- "bytes",
+ "bytes 1.5.0",
  "encoding_rs",
  "futures-core",
  "futures-util",
@@ -4167,7 +4708,7 @@ dependencies = [
  "serde_json",
  "serde_urlencoded",
  "system-configuration",
- "tokio",
+ "tokio 1.32.0",
  "tokio-native-tls",
  "tokio-util",
  "tower-service",
@@ -4196,7 +4737,7 @@ dependencies = [
  "spin",
  "untrusted",
  "web-sys",
- "winapi",
+ "winapi 0.3.9",
 ]
 
 [[package]]
@@ -4210,17 +4751,30 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "ron-parser"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c7280c46017fafbe4275179689e446a9b0db3bd91ea61aaee22841ef618405a"
+dependencies = [
+ "nom",
+ "serde",
+ "serde-wasm-bindgen",
+ "serde_json",
+ "wasm-bindgen",
+]
+
 [[package]]
 name = "router"
 version = "0.2.0"
 dependencies = [
- "actix",
  "actix-cors",
  "actix-http",
  "actix-multipart",
  "actix-rt",
  "actix-web",
  "api_models",
+ "argon2",
  "async-bb8-diesel",
  "async-trait",
  "awc",
@@ -4228,10 +4782,12 @@ dependencies = [
  "aws-sdk-s3",
  "base64 0.21.4",
  "bb8",
+ "bigdecimal",
  "blake3",
- "bytes",
+ "bytes 1.5.0",
  "cards",
  "clap",
+ "common_enums",
  "common_utils",
  "config",
  "data_models",
@@ -4242,8 +4798,9 @@ dependencies = [
  "dyn-clone",
  "encoding_rs",
  "error-stack",
+ "euclid",
  "external_services",
- "futures",
+ "futures 0.3.28",
  "hex",
  "http",
  "hyper",
@@ -4251,7 +4808,7 @@ dependencies = [
  "infer 0.13.0",
  "josekit",
  "jsonwebtoken",
- "literally",
+ "kgraph_utils",
  "masking",
  "maud",
  "mimalloc",
@@ -4262,6 +4819,7 @@ dependencies = [
  "openssl",
  "qrcode",
  "rand 0.8.5",
+ "rand_chacha 0.3.1",
  "redis_interface",
  "regex",
  "reqwest",
@@ -4269,6 +4827,7 @@ dependencies = [
  "router_derive",
  "router_env",
  "roxmltree",
+ "rustc-hash",
  "scheduler",
  "serde",
  "serde_json",
@@ -4278,21 +4837,21 @@ dependencies = [
  "serde_with",
  "serial_test",
  "sha-1 0.9.8",
- "signal-hook",
- "signal-hook-tokio",
+ "sqlx",
  "storage_impl",
  "strum 0.24.1",
  "tera",
  "test_utils",
- "thirtyfour",
  "thiserror",
  "time",
- "tokio",
- "toml 0.7.4",
+ "tokio 1.32.0",
+ "tracing-futures",
+ "unicode-segmentation",
  "url",
  "utoipa",
  "utoipa-swagger-ui",
  "uuid",
+ "validator",
  "wiremock",
  "x509-parser",
 ]
@@ -4329,7 +4888,7 @@ dependencies = [
  "serde_path_to_error",
  "strum 0.24.1",
  "time",
- "tokio",
+ "tokio 1.32.0",
  "tracing",
  "tracing-actix-web",
  "tracing-appender",
@@ -4389,7 +4948,7 @@ version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "ordered-multimap",
 ]
 
@@ -4405,13 +4964,22 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
+[[package]]
+name = "rustc_version"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+dependencies = [
+ "semver 0.9.0",
+]
+
 [[package]]
 name = "rustc_version"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
 dependencies = [
- "semver",
+ "semver 1.0.19",
 ]
 
 [[package]]
@@ -4553,7 +5121,7 @@ version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19"
 dependencies = [
- "parking_lot",
+ "parking_lot 0.12.1",
 ]
 
 [[package]]
@@ -4565,7 +5133,7 @@ dependencies = [
  "diesel_models",
  "error-stack",
  "external_services",
- "futures",
+ "futures 0.3.28",
  "masking",
  "once_cell",
  "rand 0.8.5",
@@ -4573,12 +5141,11 @@ dependencies = [
  "router_env",
  "serde",
  "serde_json",
- "signal-hook-tokio",
  "storage_impl",
  "strum 0.24.1",
  "thiserror",
  "time",
- "tokio",
+ "tokio 1.32.0",
  "uuid",
 ]
 
@@ -4627,6 +5194,15 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+dependencies = [
+ "semver-parser",
+]
+
 [[package]]
 name = "semver"
 version = "1.0.19"
@@ -4636,6 +5212,12 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+
 [[package]]
 name = "serde"
 version = "1.0.188"
@@ -4645,6 +5227,17 @@ dependencies = [
  "serde_derive",
 ]
 
+[[package]]
+name = "serde-wasm-bindgen"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e"
+dependencies = [
+ "js-sys",
+ "serde",
+ "wasm-bindgen",
+]
+
 [[package]]
 name = "serde_derive"
 version = "1.0.188"
@@ -4777,10 +5370,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0e56dd856803e253c8f298af3f4d7eb0ae5e23a737252cd90bb4f3b435033b2d"
 dependencies = [
  "dashmap",
- "futures",
+ "futures 0.3.28",
  "lazy_static",
  "log",
- "parking_lot",
+ "parking_lot 0.12.1",
  "serial_test_derive",
 ]
 
@@ -4802,7 +5395,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
 dependencies = [
  "block-buffer 0.9.0",
- "cfg-if",
+ "cfg-if 1.0.0",
  "cpufeatures",
  "digest 0.9.0",
  "opaque-debug",
@@ -4814,7 +5407,7 @@ version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "cpufeatures",
  "digest 0.10.7",
 ]
@@ -4825,7 +5418,7 @@ version = "0.10.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "cpufeatures",
  "digest 0.10.7",
 ]
@@ -4836,7 +5429,7 @@ version = "0.10.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "cpufeatures",
  "digest 0.10.7",
 ]
@@ -4887,7 +5480,7 @@ dependencies = [
  "futures-core",
  "libc",
  "signal-hook",
- "tokio",
+ "tokio 1.32.0",
 ]
 
 [[package]]
@@ -4941,6 +5534,15 @@ dependencies = [
  "deunicode",
 ]
 
+[[package]]
+name = "smallvec"
+version = "0.6.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0"
+dependencies = [
+ "maybe-uninit",
+]
+
 [[package]]
 name = "smallvec"
 version = "1.11.1"
@@ -4954,7 +5556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
 dependencies = [
  "libc",
- "winapi",
+ "winapi 0.3.9",
 ]
 
 [[package]]
@@ -4973,6 +5575,111 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
 
+[[package]]
+name = "sqlformat"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85"
+dependencies = [
+ "itertools 0.11.0",
+ "nom",
+ "unicode_categories",
+]
+
+[[package]]
+name = "sqlx"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188"
+dependencies = [
+ "sqlx-core",
+ "sqlx-macros",
+]
+
+[[package]]
+name = "sqlx-core"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029"
+dependencies = [
+ "ahash 0.7.6",
+ "atoi",
+ "base64 0.13.1",
+ "bigdecimal",
+ "bitflags 1.3.2",
+ "byteorder",
+ "bytes 1.5.0",
+ "crc",
+ "crossbeam-queue 0.3.8",
+ "dirs",
+ "dotenvy",
+ "either",
+ "event-listener",
+ "futures-channel",
+ "futures-core",
+ "futures-intrusive",
+ "futures-util",
+ "hashlink",
+ "hex",
+ "hkdf",
+ "hmac",
+ "indexmap 1.9.3",
+ "itoa",
+ "libc",
+ "log",
+ "md-5",
+ "memchr",
+ "num-bigint",
+ "once_cell",
+ "paste",
+ "percent-encoding",
+ "rand 0.8.5",
+ "serde",
+ "serde_json",
+ "sha1",
+ "sha2",
+ "smallvec 1.11.1",
+ "sqlformat",
+ "sqlx-rt",
+ "stringprep",
+ "thiserror",
+ "time",
+ "tokio-stream",
+ "url",
+ "whoami",
+]
+
+[[package]]
+name = "sqlx-macros"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9"
+dependencies = [
+ "dotenvy",
+ "either",
+ "heck",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "sha2",
+ "sqlx-core",
+ "sqlx-rt",
+ "syn 1.0.109",
+ "url",
+]
+
+[[package]]
+name = "sqlx-rt"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024"
+dependencies = [
+ "native-tls",
+ "once_cell",
+ "tokio 1.32.0",
+ "tokio-native-tls",
+]
+
 [[package]]
 name = "storage_impl"
 version = "0.1.0"
@@ -4982,7 +5689,7 @@ dependencies = [
  "async-bb8-diesel",
  "async-trait",
  "bb8",
- "bytes",
+ "bytes 1.5.0",
  "common_utils",
  "config",
  "crc32fast",
@@ -4991,8 +5698,7 @@ dependencies = [
  "diesel_models",
  "dyn-clone",
  "error-stack",
- "external_services",
- "futures",
+ "futures 0.3.28",
  "http",
  "masking",
  "mime",
@@ -5005,7 +5711,7 @@ dependencies = [
  "serde",
  "serde_json",
  "thiserror",
- "tokio",
+ "tokio 1.32.0",
 ]
 
 [[package]]
@@ -5017,6 +5723,17 @@ dependencies = [
  "regex",
 ]
 
+[[package]]
+name = "stringprep"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6"
+dependencies = [
+ "finl_unicode",
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
 [[package]]
 name = "strsim"
 version = "0.10.0"
@@ -5146,7 +5863,7 @@ version = "3.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "fastrand 2.0.1",
  "redox_syscall 0.3.5",
  "rustix 0.38.17",
@@ -5190,7 +5907,7 @@ version = "3.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "54c25e2cb8f5fcd7318157634e8838aa6f7e4715c96637f969fabaccd1ef5462"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "proc-macro-error",
  "proc-macro2",
  "quote",
@@ -5214,27 +5931,20 @@ dependencies = [
 name = "test_utils"
 version = "0.1.0"
 dependencies = [
- "actix-http",
- "actix-web",
- "api_models",
  "async-trait",
- "awc",
  "base64 0.21.4",
  "clap",
- "derive_deref",
  "masking",
  "rand 0.8.5",
  "reqwest",
  "serde",
  "serde_json",
- "serde_path_to_error",
  "serde_urlencoded",
  "serial_test",
  "thirtyfour",
  "time",
- "tokio",
+ "tokio 1.32.0",
  "toml 0.7.4",
- "uuid",
 ]
 
 [[package]]
@@ -5248,17 +5958,17 @@ dependencies = [
  "chrono",
  "cookie",
  "fantoccini",
- "futures",
+ "futures 0.3.28",
  "http",
  "log",
- "parking_lot",
+ "parking_lot 0.12.1",
  "serde",
  "serde_json",
  "serde_repr",
  "stringmatch",
  "thirtyfour-macros",
  "thiserror",
- "tokio",
+ "tokio 1.32.0",
  "url",
  "urlparse",
 ]
@@ -5301,7 +6011,7 @@ version = "1.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "once_cell",
 ]
 
@@ -5343,6 +6053,16 @@ dependencies = [
  "time-core",
 ]
 
+[[package]]
+name = "tinytemplate"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
 [[package]]
 name = "tinyvec"
 version = "1.6.0"
@@ -5358,6 +6078,30 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
+[[package]]
+name = "tokio"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6"
+dependencies = [
+ "bytes 0.4.12",
+ "futures 0.1.31",
+ "mio 0.6.23",
+ "num_cpus",
+ "tokio-codec",
+ "tokio-current-thread",
+ "tokio-executor",
+ "tokio-fs",
+ "tokio-io",
+ "tokio-reactor",
+ "tokio-sync",
+ "tokio-tcp",
+ "tokio-threadpool",
+ "tokio-timer",
+ "tokio-udp",
+ "tokio-uds",
+]
+
 [[package]]
 name = "tokio"
 version = "1.32.0"
@@ -5365,11 +6109,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9"
 dependencies = [
  "backtrace",
- "bytes",
+ "bytes 1.5.0",
  "libc",
- "mio",
+ "mio 0.8.8",
  "num_cpus",
- "parking_lot",
+ "parking_lot 0.12.1",
  "pin-project-lite",
  "signal-hook-registry",
  "socket2 0.5.4",
@@ -5377,6 +6121,59 @@ dependencies = [
  "windows-sys",
 ]
 
+[[package]]
+name = "tokio-codec"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b"
+dependencies = [
+ "bytes 0.4.12",
+ "futures 0.1.31",
+ "tokio-io",
+]
+
+[[package]]
+name = "tokio-current-thread"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e"
+dependencies = [
+ "futures 0.1.31",
+ "tokio-executor",
+]
+
+[[package]]
+name = "tokio-executor"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671"
+dependencies = [
+ "crossbeam-utils 0.7.2",
+ "futures 0.1.31",
+]
+
+[[package]]
+name = "tokio-fs"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4"
+dependencies = [
+ "futures 0.1.31",
+ "tokio-io",
+ "tokio-threadpool",
+]
+
+[[package]]
+name = "tokio-io"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674"
+dependencies = [
+ "bytes 0.4.12",
+ "futures 0.1.31",
+ "log",
+]
+
 [[package]]
 name = "tokio-io-timeout"
 version = "1.2.0"
@@ -5384,7 +6181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
 dependencies = [
  "pin-project-lite",
- "tokio",
+ "tokio 1.32.0",
 ]
 
 [[package]]
@@ -5405,7 +6202,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
 dependencies = [
  "native-tls",
- "tokio",
+ "tokio 1.32.0",
+]
+
+[[package]]
+name = "tokio-reactor"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351"
+dependencies = [
+ "crossbeam-utils 0.7.2",
+ "futures 0.1.31",
+ "lazy_static",
+ "log",
+ "mio 0.6.23",
+ "num_cpus",
+ "parking_lot 0.9.0",
+ "slab",
+ "tokio-executor",
+ "tokio-io",
+ "tokio-sync",
 ]
 
 [[package]]
@@ -5415,7 +6231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
 dependencies = [
  "rustls 0.20.9",
- "tokio",
+ "tokio 1.32.0",
  "webpki",
 ]
 
@@ -5427,7 +6243,93 @@ checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
 dependencies = [
  "futures-core",
  "pin-project-lite",
- "tokio",
+ "tokio 1.32.0",
+]
+
+[[package]]
+name = "tokio-sync"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee"
+dependencies = [
+ "fnv",
+ "futures 0.1.31",
+]
+
+[[package]]
+name = "tokio-tcp"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72"
+dependencies = [
+ "bytes 0.4.12",
+ "futures 0.1.31",
+ "iovec",
+ "mio 0.6.23",
+ "tokio-io",
+ "tokio-reactor",
+]
+
+[[package]]
+name = "tokio-threadpool"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89"
+dependencies = [
+ "crossbeam-deque 0.7.4",
+ "crossbeam-queue 0.2.3",
+ "crossbeam-utils 0.7.2",
+ "futures 0.1.31",
+ "lazy_static",
+ "log",
+ "num_cpus",
+ "slab",
+ "tokio-executor",
+]
+
+[[package]]
+name = "tokio-timer"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296"
+dependencies = [
+ "crossbeam-utils 0.7.2",
+ "futures 0.1.31",
+ "slab",
+ "tokio-executor",
+]
+
+[[package]]
+name = "tokio-udp"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82"
+dependencies = [
+ "bytes 0.4.12",
+ "futures 0.1.31",
+ "log",
+ "mio 0.6.23",
+ "tokio-codec",
+ "tokio-io",
+ "tokio-reactor",
+]
+
+[[package]]
+name = "tokio-uds"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0"
+dependencies = [
+ "bytes 0.4.12",
+ "futures 0.1.31",
+ "iovec",
+ "libc",
+ "log",
+ "mio 0.6.23",
+ "mio-uds",
+ "tokio-codec",
+ "tokio-io",
+ "tokio-reactor",
 ]
 
 [[package]]
@@ -5436,11 +6338,11 @@ version = "0.7.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d"
 dependencies = [
- "bytes",
+ "bytes 1.5.0",
  "futures-core",
  "futures-sink",
  "pin-project-lite",
- "tokio",
+ "tokio 1.32.0",
  "tracing",
 ]
 
@@ -5497,7 +6399,7 @@ dependencies = [
  "async-trait",
  "axum",
  "base64 0.13.1",
- "bytes",
+ "bytes 1.5.0",
  "futures-core",
  "futures-util",
  "h2",
@@ -5509,7 +6411,7 @@ dependencies = [
  "pin-project",
  "prost",
  "prost-derive",
- "tokio",
+ "tokio 1.32.0",
  "tokio-stream",
  "tokio-util",
  "tower",
@@ -5532,7 +6434,7 @@ dependencies = [
  "pin-project-lite",
  "rand 0.8.5",
  "slab",
- "tokio",
+ "tokio 1.32.0",
  "tokio-util",
  "tower-layer",
  "tower-service",
@@ -5557,7 +6459,7 @@ version = "0.1.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "log",
  "pin-project-lite",
  "tracing-attributes",
@@ -5566,9 +6468,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-actix-web"
-version = "0.7.7"
+version = "0.7.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94982c2ad939d5d0bfd71c2f9b7ed273c72348485c72bb87bb4db6bd69df10cb"
+checksum = "a512ec11fae6c666707625e84f83e5d58f941e9ab15723289c0d380edfe48f09"
 dependencies = [
  "actix-web",
  "opentelemetry",
@@ -5617,6 +6519,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
 dependencies = [
  "pin-project",
+ "tokio 0.1.22",
  "tracing",
 ]
 
@@ -5668,7 +6571,7 @@ dependencies = [
  "serde",
  "serde_json",
  "sharded-slab",
- "smallvec",
+ "smallvec 1.11.1",
  "thread_local",
  "tracing",
  "tracing-core",
@@ -5798,6 +6701,12 @@ version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
 
+[[package]]
+name = "unicode_categories"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
+
 [[package]]
 name = "unidecode"
 version = "0.3.0"
@@ -5880,10 +6789,26 @@ version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
 dependencies = [
+ "atomic",
  "getrandom 0.2.10",
  "serde",
 ]
 
+[[package]]
+name = "validator"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b92f40481c04ff1f4f61f304d61793c7b56ff76ac1469f1beb199b1445b253bd"
+dependencies = [
+ "idna",
+ "lazy_static",
+ "regex",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "url",
+]
+
 [[package]]
 name = "valuable"
 version = "0.1.0"
@@ -5904,7 +6829,7 @@ checksum = "8b3c89c2c7e50f33e4d35527e5bf9c11d6d132226dbbd1753f0fbe9f19ef88c6"
 dependencies = [
  "anyhow",
  "git2",
- "rustc_version",
+ "rustc_version 0.4.0",
  "rustversion",
  "time",
 ]
@@ -5973,7 +6898,7 @@ version = "0.2.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "wasm-bindgen-macro",
 ]
 
@@ -5998,7 +6923,7 @@ version = "0.4.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "js-sys",
  "wasm-bindgen",
  "web-sys",
@@ -6050,7 +6975,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9973cb72c8587d5ad5efdb91e663d36177dc37725e6c90ca86c626b0cc45c93f"
 dependencies = [
  "base64 0.13.1",
- "bytes",
+ "bytes 1.5.0",
  "cookie",
  "http",
  "log",
@@ -6087,6 +7012,22 @@ version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
 
+[[package]]
+name = "whoami"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50"
+dependencies = [
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+
 [[package]]
 name = "winapi"
 version = "0.3.9"
@@ -6097,6 +7038,12 @@ dependencies = [
  "winapi-x86_64-pc-windows-gnu",
 ]
 
+[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+
 [[package]]
 name = "winapi-i686-pc-windows-gnu"
 version = "0.4.0"
@@ -6109,7 +7056,7 @@ version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
 dependencies = [
- "winapi",
+ "winapi 0.3.9",
 ]
 
 [[package]]
@@ -6208,7 +7155,7 @@ version = "0.50.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
 dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
  "windows-sys",
 ]
 
@@ -6222,7 +7169,7 @@ dependencies = [
  "async-trait",
  "base64 0.21.4",
  "deadpool",
- "futures",
+ "futures 0.3.28",
  "futures-timer",
  "http-types",
  "hyper",
@@ -6231,7 +7178,17 @@ dependencies = [
  "regex",
  "serde",
  "serde_json",
- "tokio",
+ "tokio 1.32.0",
+]
+
+[[package]]
+name = "ws2_32-sys"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
+dependencies = [
+ "winapi 0.2.8",
+ "winapi-build",
 ]
 
 [[package]]
@@ -6280,7 +7237,7 @@ checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
 dependencies = [
  "byteorder",
  "crc32fast",
- "crossbeam-utils",
+ "crossbeam-utils 0.8.16",
  "flate2",
 ]
 
diff --git a/README.md b/README.md
index cc19670a8fc3..129a0512d4a0 100644
--- a/README.md
+++ b/README.md
@@ -35,19 +35,11 @@ The single API to access payment ecosystems across 130+ countries</div>
   </a>
 </p>
 
-<h1 align="center">🎉 Hacktoberfest is here! 🎉</h1>
-
-New to Rust? Hyperswitch is the perfect place to start this hacktoberfest! 😁
-
-> ⭐️ If you're new to Hacktoberfest, you can learn more and register to participate [here](https://hacktoberfest.com/participation/). Registration is from **September 26th - October 31st**.
-
 
 <hr>
 <img src="./docs/imgs/switch.png" />
 
-Hyperswitch is an open source payments switch to make payments fast, reliable, and, affordable.
-It lets you connect with multiple payment processors and route traffic effortlessly, all with a single API integration.
-
+Hyperswitch is a community-led, open payments switch to enable access to the best payments infrastructure for every digital business.
 
 Using Hyperswitch, you can:
 
@@ -58,8 +50,6 @@ Using Hyperswitch, you can:
 - 🎨 **Customize payment flows** with full visibility and control
 - 🌐 **Increase business reach** with local/alternate payment methods
 
-> Hyperswitch is **wire-compatible** with top processors like Stripe, making it easy to integrate.
-
 <br>
 <img src="./docs/imgs/hyperswitch-product.png" alt="Hyperswitch-Product" width="50%"/>
 
@@ -67,24 +57,23 @@ Using Hyperswitch, you can:
   <h2 id="Quick Start Guide">⚡️ Quick Start Guide</h2>
 </a>
 
+<h3> One-click deployment on AWS cloud </h3>
 
-<a href="https://app.hyperswitch.io/register"><img src="./docs/imgs/signup-to-hs.svg" height="35"></a>
+The fastest and easiest way to try hyperswitch is via our CDK scripts
 
-Ways to get started with Hyperswitch:
+1. Click on the following button for a quick standalone deployment on AWS, suitable for prototyping.
+   No code or setup is required in your system and the deployment is covered within the AWS free-tier setup.
 
-1. Try it in our Sandbox Environment: Fast and easy to
-   start.
-   No code or setup is required in your system, [learn more](/docs/try_sandbox.md)
+&emsp;&emsp; <a title="Bootstrap" href="https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=cdk-hs&templateURL=https://hyperswitch-synth.s3.eu-central-1.amazonaws.com/bootstrap-template.yml"> Click here if you have not bootstrapped your region before deploying</a>
 
+&emsp;&emsp; <a href="https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=Hyperswitch&templateURL=https://hyperswitch-synth.s3.eu-central-1.amazonaws.com/deployment.yaml"><img src="./docs/imgs/aws_button.png" height="35"></a>
 
-<a href="https://app.hyperswitch.io/register"><img src="./docs/imgs/get-api-keys.svg" height="35"></a>
 
-2. A simple demo of integrating Hyperswitch with your React App, Try our React [Demo App](https://github.com/aashu331998/hyperswitch-react-demo-app/archive/refs/heads/main.zip).
+2. Sign-in to your AWS console.
 
+3. Follow the instructions provided on the console to successfully deploy Hyperswitch
 
-3. Install in your local system: Configurations and
-   setup required in your system.
-   Suitable if you like to customise the core offering, [setup guide](/docs/try_local_system.md)
+For an early access to the production-ready setup fill this <a href="https://forms.gle/v6ru55XDZFufVPnu9">Early Access Form</a>
 
 <a href="#Fast-Integration-for-Stripe-Users">
   <h2 id="Fast Integration for Stripe Users">🔌 Fast Integration for Stripe Users</h2>
diff --git a/aws/beta_schema.sql b/aws/beta_schema.sql
new file mode 100644
index 000000000000..439d1792231c
--- /dev/null
+++ b/aws/beta_schema.sql
@@ -0,0 +1,2252 @@
+-- File: migrations/00000000000000_diesel_initial_setup/up.sql
+-- This file was automatically created by Diesel to setup helper functions
+-- and other internal bookkeeping. This file is safe to edit, any future
+-- changes will be added to existing projects as new migrations.
+
+
+
+
+-- Sets up a trigger for the given table to automatically set a column called
+-- `updated_at` whenever the row is modified (unless `updated_at` was included
+-- in the modified columns)
+--
+-- # Example
+--
+-- ```sql
+-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
+--
+-- SELECT diesel_manage_updated_at('users');
+-- ```
+CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
+BEGIN
+    EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
+                    FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
+BEGIN
+    IF (
+        NEW IS DISTINCT FROM OLD AND
+        NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
+    ) THEN
+        NEW.updated_at := current_timestamp;
+    END IF;
+    RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- File: migrations/2022-09-29-084920_create_initial_tables/up.sql
+-- Types
+CREATE TYPE "AttemptStatus" AS ENUM (
+    'started',
+    'authentication_failed',
+    'juspay_declined',
+    'pending_vbv',
+    'vbv_successful',
+    'authorized',
+    'authorization_failed',
+    'charged',
+    'authorizing',
+    'cod_initiated',
+    'voided',
+    'void_initiated',
+    'capture_initiated',
+    'capture_failed',
+    'void_failed',
+    'auto_refunded',
+    'partial_charged',
+    'pending',
+    'failure',
+    'payment_method_awaited',
+    'confirmation_awaited'
+);
+
+CREATE TYPE "AuthenticationType" AS ENUM ('three_ds', 'no_three_ds');
+
+CREATE TYPE "CaptureMethod" AS ENUM ('automatic', 'manual', 'scheduled');
+
+CREATE TYPE "ConnectorType" AS ENUM (
+    'payment_processor',
+    'payment_vas',
+    'fin_operations',
+    'fiz_operations',
+    'networks',
+    'banking_entities',
+    'non_banking_finance'
+);
+
+CREATE TYPE "Currency" AS ENUM (
+    'AED',
+    'ALL',
+    'AMD',
+    'ARS',
+    'AUD',
+    'AWG',
+    'AZN',
+    'BBD',
+    'BDT',
+    'BHD',
+    'BMD',
+    'BND',
+    'BOB',
+    'BRL',
+    'BSD',
+    'BWP',
+    'BZD',
+    'CAD',
+    'CHF',
+    'CNY',
+    'COP',
+    'CRC',
+    'CUP',
+    'CZK',
+    'DKK',
+    'DOP',
+    'DZD',
+    'EGP',
+    'ETB',
+    'EUR',
+    'FJD',
+    'GBP',
+    'GHS',
+    'GIP',
+    'GMD',
+    'GTQ',
+    'GYD',
+    'HKD',
+    'HNL',
+    'HRK',
+    'HTG',
+    'HUF',
+    'IDR',
+    'ILS',
+    'INR',
+    'JMD',
+    'JOD',
+    'JPY',
+    'KES',
+    'KGS',
+    'KHR',
+    'KRW',
+    'KWD',
+    'KYD',
+    'KZT',
+    'LAK',
+    'LBP',
+    'LKR',
+    'LRD',
+    'LSL',
+    'MAD',
+    'MDL',
+    'MKD',
+    'MMK',
+    'MNT',
+    'MOP',
+    'MUR',
+    'MVR',
+    'MWK',
+    'MXN',
+    'MYR',
+    'NAD',
+    'NGN',
+    'NIO',
+    'NOK',
+    'NPR',
+    'NZD',
+    'OMR',
+    'PEN',
+    'PGK',
+    'PHP',
+    'PKR',
+    'PLN',
+    'QAR',
+    'RUB',
+    'SAR',
+    'SCR',
+    'SEK',
+    'SGD',
+    'SLL',
+    'SOS',
+    'SSP',
+    'SVC',
+    'SZL',
+    'THB',
+    'TTD',
+    'TWD',
+    'TZS',
+    'USD',
+    'UYU',
+    'UZS',
+    'YER',
+    'ZAR'
+);
+
+CREATE TYPE "EventClass" AS ENUM ('payments');
+
+CREATE TYPE "EventObjectType" AS ENUM ('payment_details');
+
+CREATE TYPE "EventType" AS ENUM ('payment_succeeded');
+
+CREATE TYPE "FutureUsage" AS ENUM ('on_session', 'off_session');
+
+CREATE TYPE "IntentStatus" AS ENUM (
+    'succeeded',
+    'failed',
+    'processing',
+    'requires_customer_action',
+    'requires_payment_method',
+    'requires_confirmation'
+);
+
+CREATE TYPE "MandateStatus" AS ENUM (
+    'active',
+    'inactive',
+    'pending',
+    'revoked'
+);
+
+CREATE TYPE "MandateType" AS ENUM ('single_use', 'multi_use');
+
+CREATE TYPE "PaymentFlow" AS ENUM (
+    'vsc',
+    'emi',
+    'otp',
+    'upi_intent',
+    'upi_collect',
+    'upi_scan_and_pay',
+    'sdk'
+);
+
+CREATE TYPE "PaymentMethodIssuerCode" AS ENUM (
+    'jp_hdfc',
+    'jp_icici',
+    'jp_googlepay',
+    'jp_applepay',
+    'jp_phonepe',
+    'jp_wechat',
+    'jp_sofort',
+    'jp_giropay',
+    'jp_sepa',
+    'jp_bacs'
+);
+
+CREATE TYPE "PaymentMethodSubType" AS ENUM (
+    'credit',
+    'debit',
+    'upi_intent',
+    'upi_collect',
+    'credit_card_installments',
+    'pay_later_installments'
+);
+
+CREATE TYPE "PaymentMethodType" AS ENUM (
+    'card',
+    'bank_transfer',
+    'netbanking',
+    'upi',
+    'open_banking',
+    'consumer_finance',
+    'wallet',
+    'payment_container',
+    'bank_debit',
+    'pay_later'
+);
+
+CREATE TYPE "ProcessTrackerStatus" AS ENUM (
+    'processing',
+    'new',
+    'pending',
+    'process_started',
+    'finish'
+);
+
+CREATE TYPE "RefundStatus" AS ENUM (
+    'failure',
+    'manual_review',
+    'pending',
+    'success',
+    'transaction_failure'
+);
+
+CREATE TYPE "RefundType" AS ENUM (
+    'instant_refund',
+    'regular_refund',
+    'retry_refund'
+);
+
+CREATE TYPE "RoutingAlgorithm" AS ENUM (
+    'round_robin',
+    'max_conversion',
+    'min_cost',
+    'custom'
+);
+
+-- Tables
+CREATE TABLE address (
+    id SERIAL,
+    address_id VARCHAR(255) PRIMARY KEY,
+    city VARCHAR(255),
+    country VARCHAR(255),
+    line1 VARCHAR(255),
+    line2 VARCHAR(255),
+    line3 VARCHAR(255),
+    state VARCHAR(255),
+    zip VARCHAR(255),
+    first_name VARCHAR(255),
+    last_name VARCHAR(255),
+    phone_number VARCHAR(255),
+    country_code VARCHAR(255),
+    created_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP,
+    modified_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP
+);
+
+CREATE TABLE configs (
+    id SERIAL,
+    key VARCHAR(255) NOT NULL,
+    config TEXT NOT NULL,
+    PRIMARY KEY (key)
+);
+
+CREATE TABLE customers (
+    id SERIAL,
+    customer_id VARCHAR(255) NOT NULL,
+    merchant_id VARCHAR(255) NOT NULL,
+    NAME VARCHAR(255),
+    email VARCHAR(255),
+    phone VARCHAR(255),
+    phone_country_code VARCHAR(255),
+    description VARCHAR(255),
+    address JSON,
+    created_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP,
+    metadata JSON,
+    PRIMARY KEY (customer_id, merchant_id)
+);
+
+CREATE TABLE events (
+    id SERIAL PRIMARY KEY,
+    event_id VARCHAR(255) NOT NULL,
+    event_type "EventType" NOT NULL,
+    event_class "EventClass" NOT NULL,
+    is_webhook_notified BOOLEAN NOT NULL DEFAULT FALSE,
+    intent_reference_id VARCHAR(255),
+    primary_object_id VARCHAR(255) NOT NULL,
+    primary_object_type "EventObjectType" NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP
+);
+
+CREATE TABLE locker_mock_up (
+    id SERIAL PRIMARY KEY,
+    card_id VARCHAR(255) NOT NULL,
+    external_id VARCHAR(255) NOT NULL,
+    card_fingerprint VARCHAR(255) NOT NULL,
+    card_global_fingerprint VARCHAR(255) NOT NULL,
+    merchant_id VARCHAR(255) NOT NULL,
+    card_number VARCHAR(255) NOT NULL,
+    card_exp_year VARCHAR(255) NOT NULL,
+    card_exp_month VARCHAR(255) NOT NULL,
+    name_on_card VARCHAR(255),
+    nickname VARCHAR(255),
+    customer_id VARCHAR(255),
+    duplicate BOOLEAN
+);
+
+CREATE TABLE mandate (
+    id SERIAL PRIMARY KEY,
+    mandate_id VARCHAR(255) NOT NULL,
+    customer_id VARCHAR(255) NOT NULL,
+    merchant_id VARCHAR(255) NOT NULL,
+    payment_method_id VARCHAR(255) NOT NULL,
+    mandate_status "MandateStatus" NOT NULL,
+    mandate_type "MandateType" NOT NULL,
+    customer_accepted_at TIMESTAMP,
+    customer_ip_address VARCHAR(255),
+    customer_user_agent VARCHAR(255),
+    network_transaction_id VARCHAR(255),
+    previous_transaction_id VARCHAR(255),
+    created_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP
+);
+
+CREATE TABLE merchant_account (
+    id SERIAL PRIMARY KEY,
+    merchant_id VARCHAR(255) NOT NULL,
+    api_key VARCHAR(255),
+    return_url VARCHAR(255),
+    enable_payment_response_hash BOOLEAN NOT NULL DEFAULT FALSE,
+    payment_response_hash_key VARCHAR(255) DEFAULT NULL,
+    redirect_to_merchant_with_http_post BOOLEAN NOT NULL DEFAULT FALSE,
+    merchant_name VARCHAR(255),
+    merchant_details JSON,
+    webhook_details JSON,
+    routing_algorithm "RoutingAlgorithm",
+    custom_routing_rules JSON,
+    sub_merchants_enabled BOOLEAN DEFAULT FALSE,
+    parent_merchant_id VARCHAR(255),
+    publishable_key VARCHAR(255)
+);
+
+CREATE TABLE merchant_connector_account (
+    id SERIAL PRIMARY KEY,
+    merchant_id VARCHAR(255) NOT NULL,
+    connector_name VARCHAR(255) NOT NULL,
+    connector_account_details JSON NOT NULL,
+    test_mode BOOLEAN,
+    disabled BOOLEAN,
+    merchant_connector_id SERIAL NOT NULL,
+    payment_methods_enabled JSON [ ],
+    connector_type "ConnectorType" NOT NULL DEFAULT 'payment_processor'::"ConnectorType"
+);
+
+CREATE TABLE payment_attempt (
+    id SERIAL PRIMARY KEY,
+    payment_id VARCHAR(255) NOT NULL,
+    merchant_id VARCHAR(255) NOT NULL,
+    txn_id VARCHAR(255) NOT NULL,
+    status "AttemptStatus" NOT NULL,
+    amount INTEGER NOT NULL,
+    currency "Currency",
+    save_to_locker BOOLEAN,
+    connector VARCHAR(255) NOT NULL,
+    error_message TEXT,
+    offer_amount INTEGER,
+    surcharge_amount INTEGER,
+    tax_amount INTEGER,
+    payment_method_id VARCHAR(255),
+    payment_method "PaymentMethodType",
+    payment_flow "PaymentFlow",
+    redirect BOOLEAN,
+    connector_transaction_id VARCHAR(255),
+    capture_method "CaptureMethod",
+    capture_on TIMESTAMP,
+    confirm BOOLEAN NOT NULL,
+    authentication_type "AuthenticationType",
+    created_at TIMESTAMP NOT NULL,
+    modified_at TIMESTAMP NOT NULL,
+    last_synced TIMESTAMP
+);
+
+CREATE TABLE payment_intent (
+    id SERIAL PRIMARY KEY,
+    payment_id VARCHAR(255) NOT NULL,
+    merchant_id VARCHAR(255) NOT NULL,
+    status "IntentStatus" NOT NULL,
+    amount INTEGER NOT NULL,
+    currency "Currency",
+    amount_captured INTEGER,
+    customer_id VARCHAR(255),
+    description VARCHAR(255),
+    return_url VARCHAR(255),
+    metadata JSONB DEFAULT '{}'::JSONB,
+    connector_id VARCHAR(255),
+    shipping_address_id VARCHAR(255),
+    billing_address_id VARCHAR(255),
+    statement_descriptor_name VARCHAR(255),
+    statement_descriptor_suffix VARCHAR(255),
+    created_at TIMESTAMP NOT NULL,
+    modified_at TIMESTAMP NOT NULL,
+    last_synced TIMESTAMP,
+    setup_future_usage "FutureUsage",
+    off_session BOOLEAN,
+    client_secret VARCHAR(255)
+);
+
+CREATE TABLE payment_methods (
+    id SERIAL PRIMARY KEY,
+    customer_id VARCHAR(255) NOT NULL,
+    merchant_id VARCHAR(255) NOT NULL,
+    payment_method_id VARCHAR(255) NOT NULL,
+    accepted_currency "Currency" [ ],
+    scheme VARCHAR(255),
+    token VARCHAR(255),
+    cardholder_name VARCHAR(255),
+    issuer_name VARCHAR(255),
+    issuer_country VARCHAR(255),
+    payer_country TEXT [ ],
+    is_stored BOOLEAN,
+    swift_code VARCHAR(255),
+    direct_debit_token VARCHAR(255),
+    network_transaction_id VARCHAR(255),
+    created_at TIMESTAMP NOT NULL,
+    last_modified TIMESTAMP NOT NULL,
+    payment_method "PaymentMethodType" NOT NULL,
+    payment_method_type "PaymentMethodSubType",
+    payment_method_issuer VARCHAR(255),
+    payment_method_issuer_code "PaymentMethodIssuerCode"
+);
+
+CREATE TABLE process_tracker (
+    id VARCHAR(127) PRIMARY KEY,
+    NAME VARCHAR(255),
+    tag TEXT [ ] NOT NULL DEFAULT '{}'::TEXT [ ],
+    runner VARCHAR(255),
+    retry_count INTEGER NOT NULL,
+    schedule_time TIMESTAMP,
+    rule VARCHAR(255) NOT NULL,
+    tracking_data JSON NOT NULL,
+    business_status VARCHAR(255) NOT NULL,
+    status "ProcessTrackerStatus" NOT NULL,
+    event TEXT [ ] NOT NULL DEFAULT '{}'::TEXT [ ],
+    created_at TIMESTAMP NOT NULL DEFAULT now(),
+    updated_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE TABLE refund (
+    id SERIAL PRIMARY KEY,
+    internal_reference_id VARCHAR(255) NOT NULL,
+    refund_id VARCHAR(255) NOT NULL,
+    payment_id VARCHAR(255) NOT NULL,
+    merchant_id VARCHAR(255) NOT NULL,
+    transaction_id VARCHAR(255) NOT NULL,
+    connector VARCHAR(255) NOT NULL,
+    pg_refund_id VARCHAR(255),
+    external_reference_id VARCHAR(255),
+    refund_type "RefundType" NOT NULL,
+    total_amount INTEGER NOT NULL,
+    currency "Currency" NOT NULL,
+    refund_amount INTEGER NOT NULL,
+    refund_status "RefundStatus" NOT NULL,
+    sent_to_gateway BOOLEAN NOT NULL DEFAULT FALSE,
+    refund_error_message TEXT,
+    metadata JSON,
+    refund_arn VARCHAR(255),
+    created_at TIMESTAMP NOT NULL,
+    modified_at TIMESTAMP NOT NULL,
+    description VARCHAR(255)
+);
+
+CREATE TABLE temp_card (
+    id SERIAL PRIMARY KEY,
+    date_created TIMESTAMP NOT NULL,
+    txn_id VARCHAR(255),
+    card_info JSON
+);
+
+-- Indices
+CREATE INDEX customers_created_at_index ON customers (created_at);
+
+CREATE UNIQUE INDEX merchant_account_api_key_index ON merchant_account (api_key);
+
+CREATE UNIQUE INDEX merchant_account_merchant_id_index ON merchant_account (merchant_id);
+
+CREATE UNIQUE INDEX merchant_account_publishable_key_index ON merchant_account (publishable_key);
+
+CREATE INDEX merchant_connector_account_connector_type_index ON merchant_connector_account (connector_type);
+
+CREATE INDEX merchant_connector_account_merchant_id_index ON merchant_connector_account (merchant_id);
+
+CREATE UNIQUE INDEX payment_attempt_payment_id_merchant_id_index ON payment_attempt (payment_id, merchant_id);
+
+CREATE UNIQUE INDEX payment_intent_payment_id_merchant_id_index ON payment_intent (payment_id, merchant_id);
+
+CREATE INDEX payment_methods_created_at_index ON payment_methods (created_at);
+
+CREATE INDEX payment_methods_customer_id_index ON payment_methods (customer_id);
+
+CREATE INDEX payment_methods_last_modified_index ON payment_methods (last_modified);
+
+CREATE INDEX payment_methods_payment_method_id_index ON payment_methods (payment_method_id);
+
+CREATE INDEX refund_internal_reference_id_index ON refund (internal_reference_id);
+
+CREATE INDEX refund_payment_id_merchant_id_index ON refund (payment_id, merchant_id);
+
+CREATE INDEX refund_refund_id_index ON refund (refund_id);
+
+CREATE UNIQUE INDEX refund_refund_id_merchant_id_index ON refund (refund_id, merchant_id);
+
+CREATE INDEX temp_card_txn_id_index ON temp_card (txn_id);
+
+
+
+-- File: migrations/2022-09-29-093314_create_seed_data/up.sql
+INSERT INTO merchant_account (
+        merchant_id,
+        api_key,
+        merchant_name,
+        merchant_details,
+        custom_routing_rules,
+        publishable_key
+    )
+VALUES (
+        'juspay_merchant',
+        'MySecretApiKey',
+        'Juspay Merchant',
+        '{ "primary_email": "merchant@juspay.in" }',
+        '[ { "connectors_pecking_order": [ "stripe" ] } ]',
+        'pk_MyPublicApiKey'
+    );
+
+INSERT INTO merchant_connector_account (
+        merchant_id,
+        connector_name,
+        connector_account_details
+    )
+VALUES (
+        'juspay_merchant',
+        'stripe',
+        '{ "auth_type": "HeaderKey", "api_key": "Basic MyStripeApiKey" }'
+    );
+
+
+
+-- File: migrations/2022-10-20-100628_add_cancellation_reason/up.sql
+ALTER TABLE payment_attempt
+ADD COLUMN cancellation_reason VARCHAR(255);
+
+
+
+-- File: migrations/2022-10-26-101016_update_payment_attempt_status_intent_status/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_attempt ADD IF NOT EXISTS amount_to_capture INTEGER;
+ALTER TYPE "CaptureMethod" ADD VALUE 'manual_multiple' AFTER 'manual';
+ALTER TYPE "IntentStatus" ADD VALUE 'requires_capture';
+
+
+-- File: migrations/2022-11-03-130214_create_connector_response_table/up.sql
+-- Your SQL goes here
+CREATE TABLE connector_response (
+    id SERIAL PRIMARY KEY,
+    payment_id VARCHAR(255) NOT NULL,
+    merchant_id VARCHAR(255) NOT NULL,
+    txn_id VARCHAR(255) NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP,
+    modified_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP,
+    connector_name VARCHAR(32) NOT NULL,
+    connector_transaction_id VARCHAR(255),
+    authentication_data JSON,
+    encoded_data TEXT
+);
+
+CREATE UNIQUE INDEX connector_response_id_index ON connector_response (payment_id, merchant_id, txn_id);
+
+
+-- File: migrations/2022-11-08-101705_add_cancel_to_payment_intent_status/up.sql
+-- Your SQL goes here
+ALTER TYPE "IntentStatus" ADD VALUE 'cancelled' after 'failed';
+
+
+
+
+-- File: migrations/2022-11-21-133803_add_mandate_id_in_payment_attempt/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_attempt ADD IF NOT EXISTS mandate_id VARCHAR(255);
+
+
+
+-- File: migrations/2022-11-24-095709_add_browser_info_to_payment_attempt/up.sql
+ALTER TABLE payment_attempt
+ADD COLUMN browser_info JSONB DEFAULT NULL;
+
+
+
+-- File: migrations/2022-11-25-121143_add_paypal_pmt/up.sql
+-- Your SQL goes here
+ALTER TYPE "PaymentMethodType" ADD VALUE 'paypal' after 'pay_later';
+
+
+
+-- File: migrations/2022-11-30-084736_update-index-in-mca/up.sql
+CREATE UNIQUE INDEX merchant_connector_account_merchant_id_connector_name_index ON merchant_connector_account (merchant_id, connector_name);
+
+
+-- File: migrations/2022-12-05-090521_single_use_mandate_fields/up.sql
+-- Your SQL goes here
+ALTER TABLE mandate
+ADD IF NOT EXISTS single_use_amount INTEGER DEFAULT NULL,
+ADD IF NOT EXISTS single_use_currency "Currency" DEFAULT NULL;
+
+
+
+-- File: migrations/2022-12-07-055441_add_use_kv_to_merchant_account/up.sql
+-- Your SQL goes here
+
+CREATE TYPE "MerchantStorageScheme" AS ENUM (
+    'postgres_only',
+    'redis_kv'
+);
+
+ALTER TABLE merchant_account ADD COLUMN storage_scheme "MerchantStorageScheme" NOT NULL DEFAULT 'postgres_only';
+
+
+
+-- File: migrations/2022-12-07-133736_make_connector_field_optional/up.sql
+ALTER TABLE payment_attempt ALTER COLUMN connector DROP NOT NULL;
+ALTER TABLE connector_response ALTER COLUMN connector_name DROP NOT NULL;
+
+
+-- File: migrations/2022-12-09-102635_mandate-connector-and-amount/up.sql
+-- Your SQL goes here
+ALTER TABLE mandate
+RENAME COLUMN single_use_amount TO mandate_amount;
+ALTER TABLE mandate
+RENAME COLUMN single_use_currency TO mandate_currency;
+ALTER TABLE mandate
+ADD IF NOT EXISTS amount_captured INTEGER DEFAULT NULL,
+ADD IF NOT EXISTS connector VARCHAR(255) NOT NULL DEFAULT 'dummy',
+ADD IF NOT EXISTS connector_mandate_id VARCHAR(255) DEFAULT NULL;
+
+
+-- File: migrations/2022-12-10-123613_update_address_and_customer/up.sql
+-- Your SQL goes here
+ALTER TABLE address
+ADD COLUMN customer_id VARCHAR(255) NOT NULL,
+ADD COLUMN merchant_id VARCHAR(255) NOT NULL;
+
+CREATE INDEX address_customer_id_merchant_id_index ON address (customer_id, merchant_id);
+
+ALTER TABLE customers DROP COLUMN address;
+
+
+-- File: migrations/2022-12-11-190755_update_mock_up/up.sql
+-- Your SQL goes here
+ALTER TABLE locker_mock_up
+ADD COLUMN card_cvc VARCHAR(8);
+
+
+-- File: migrations/2022-12-12-132936_reverse_lookup/up.sql
+CREATE TABLE reverse_lookup (
+    lookup_id VARCHAR(255) NOT NULL PRIMARY KEY,
+    sk_id VARCHAR(50) NOT NULL,
+    pk_id VARCHAR(255) NOT NULL,
+    source VARCHAR(30) NOT NULL
+);
+
+CREATE INDEX lookup_id_index ON reverse_lookup (lookup_id);
+
+
+
+-- File: migrations/2022-12-13-170152_add_connector_metadata/up.sql
+ALTER TABLE merchant_connector_account ADD COLUMN metadata JSONB DEFAULT NULL;
+
+
+
+-- File: migrations/2022-12-14-074547_error-code-in-payment_attempt/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_attempt
+ADD IF NOT EXISTS error_code VARCHAR(255) DEFAULT NULL;
+
+
+-- File: migrations/2022-12-14-090419_add_payment_token_in_payment_attempt/up.sql
+ALTER TABLE payment_attempt ADD COLUMN payment_token VARCHAR(255);
+
+
+-- File: migrations/2022-12-14-092540_i32_to_i64/up.sql
+-- Your SQL goes here
+ALTER TABLE mandate
+    ALTER COLUMN mandate_amount TYPE bigint,
+    ALTER COLUMN amount_captured TYPE bigint;
+
+ALTER TABLE payment_attempt
+    ALTER COLUMN amount TYPE bigint,
+    ALTER COLUMN offer_amount TYPE bigint,
+    ALTER COLUMN surcharge_amount TYPE bigint,
+    ALTER COLUMN tax_amount TYPE bigint,
+    ALTER COLUMN amount_to_capture TYPE bigint;
+
+ALTER TABLE payment_intent
+    ALTER COLUMN amount TYPE bigint,
+    ALTER COLUMN amount_captured TYPE bigint;
+
+ALTER TABLE refund
+    ALTER COLUMN total_amount TYPE bigint,
+    ALTER COLUMN refund_amount TYPE bigint;
+
+
+
+-- File: migrations/2022-12-14-162701_update_payment_method/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_methods
+ADD COLUMN metadata JSON;
+
+
+-- File: migrations/2022-12-19-085322_rename_txn_id_to_attempt_id/up.sql
+ALTER TABLE payment_attempt
+RENAME COLUMN txn_id to attempt_id;
+
+
+
+-- File: migrations/2022-12-19-085739_add_attempt_id_to_refund/up.sql
+ALTER TABLE refund ADD COLUMN attempt_id VARCHAR(64) NOT NULL;
+
+
+
+-- File: migrations/2022-12-20-065945_reduce_size_of_varchar_columns/up.sql
+ALTER TABLE address
+    ALTER COLUMN address_id TYPE VARCHAR(64),
+    ALTER COLUMN city TYPE VARCHAR(128),
+    ALTER COLUMN country TYPE VARCHAR(64),
+    ALTER COLUMN state TYPE VARCHAR(128),
+    ALTER COLUMN zip TYPE VARCHAR(16),
+    ALTER COLUMN phone_number TYPE VARCHAR(32),
+    ALTER COLUMN country_code TYPE VARCHAR(8),
+    ALTER COLUMN customer_id TYPE VARCHAR(64),
+    ALTER COLUMN merchant_id TYPE VARCHAR(64);
+
+ALTER TABLE connector_response RENAME COLUMN txn_id TO attempt_id;
+
+ALTER TABLE connector_response
+    ALTER COLUMN payment_id TYPE VARCHAR(64),
+    ALTER COLUMN merchant_id TYPE VARCHAR(64),
+    ALTER COLUMN attempt_id TYPE VARCHAR(64),
+    ALTER COLUMN connector_name TYPE VARCHAR(64),
+    ALTER COLUMN connector_transaction_id TYPE VARCHAR(128);
+
+ALTER TABLE customers
+    ALTER COLUMN customer_id TYPE VARCHAR(64),
+    ALTER COLUMN merchant_id TYPE VARCHAR(64),
+    ALTER COLUMN phone TYPE VARCHAR(32),
+    ALTER COLUMN phone_country_code TYPE VARCHAR(8);
+
+ALTER TABLE events
+    ALTER COLUMN event_id TYPE VARCHAR(64),
+    ALTER COLUMN intent_reference_id TYPE VARCHAR(64),
+    ALTER COLUMN primary_object_id TYPE VARCHAR(64);
+
+ALTER TABLE mandate RENAME COLUMN previous_transaction_id to previous_attempt_id;
+
+ALTER TABLE mandate
+    ALTER COLUMN mandate_id TYPE VARCHAR(64),
+    ALTER COLUMN customer_id TYPE VARCHAR(64),
+    ALTER COLUMN merchant_id TYPE VARCHAR(64),
+    ALTER COLUMN payment_method_id TYPE VARCHAR(64),
+    ALTER COLUMN customer_ip_address TYPE VARCHAR(64),
+    ALTER COLUMN network_transaction_id TYPE VARCHAR(128),
+    ALTER COLUMN previous_attempt_id TYPE VARCHAR(64),
+    ALTER COLUMN connector TYPE VARCHAR(64),
+    ALTER COLUMN connector_mandate_id TYPE VARCHAR(128);
+
+ALTER TABLE merchant_account
+    ALTER COLUMN merchant_id TYPE VARCHAR(64),
+    ALTER COLUMN api_key TYPE VARCHAR(128),
+    ALTER COLUMN merchant_name TYPE VARCHAR(128),
+    ALTER COLUMN parent_merchant_id TYPE VARCHAR(64),
+    ALTER COLUMN publishable_key TYPE VARCHAR(128);
+
+ALTER TABLE merchant_connector_account
+    ALTER COLUMN merchant_id TYPE VARCHAR(64),
+    ALTER COLUMN connector_name TYPE VARCHAR(64);
+
+ALTER TABLE payment_attempt
+    ALTER COLUMN payment_id TYPE VARCHAR(64),
+    ALTER COLUMN merchant_id TYPE VARCHAR(64),
+    ALTER COLUMN attempt_id TYPE VARCHAR(64),
+    ALTER COLUMN connector TYPE VARCHAR(64),
+    ALTER COLUMN payment_method_id TYPE VARCHAR(64),
+    ALTER COLUMN connector_transaction_id TYPE VARCHAR(128),
+    ALTER COLUMN mandate_id TYPE VARCHAR(64),
+    ALTER COLUMN payment_token TYPE VARCHAR(128);
+
+ALTER TABLE payment_intent
+    ALTER COLUMN payment_id TYPE VARCHAR(64),
+    ALTER COLUMN merchant_id TYPE VARCHAR(64),
+    ALTER COLUMN customer_id TYPE VARCHAR(64),
+    ALTER COLUMN connector_id TYPE VARCHAR(64),
+    ALTER COLUMN shipping_address_id TYPE VARCHAR(64),
+    ALTER COLUMN billing_address_id TYPE VARCHAR(64),
+    ALTER COLUMN client_secret TYPE VARCHAR(128);
+
+ALTER TABLE payment_methods DROP COLUMN network_transaction_id;
+
+ALTER TABLE payment_methods
+    ALTER COLUMN customer_id TYPE VARCHAR(64),
+    ALTER COLUMN merchant_id TYPE VARCHAR(64),
+    ALTER COLUMN payment_method_id TYPE VARCHAR(64),
+    ALTER COLUMN scheme TYPE VARCHAR(32),
+    ALTER COLUMN token TYPE VARCHAR(128),
+    ALTER COLUMN issuer_name TYPE VARCHAR(64),
+    ALTER COLUMN issuer_country TYPE VARCHAR(64),
+    ALTER COLUMN swift_code TYPE VARCHAR(32),
+    ALTER COLUMN direct_debit_token TYPE VARCHAR(128),
+    ALTER COLUMN payment_method_issuer TYPE VARCHAR(128);
+
+ALTER TABLE process_tracker
+    ALTER COLUMN name TYPE VARCHAR(64),
+    ALTER COLUMN runner TYPE VARCHAR(64);
+
+ALTER TABLE refund RENAME COLUMN transaction_id to connector_transaction_id;
+ALTER TABLE refund RENAME COLUMN pg_refund_id to connector_refund_id;
+
+ALTER TABLE refund
+    ALTER COLUMN internal_reference_id TYPE VARCHAR(64),
+    ALTER COLUMN refund_id TYPE VARCHAR(64),
+    ALTER COLUMN payment_id TYPE VARCHAR(64),
+    ALTER COLUMN merchant_id TYPE VARCHAR(64),
+    ALTER COLUMN connector_transaction_id TYPE VARCHAR(128),
+    ALTER COLUMN connector TYPE VARCHAR(64),
+    ALTER COLUMN connector_refund_id TYPE VARCHAR(128),
+    ALTER COLUMN external_reference_id TYPE VARCHAR(64),
+    ALTER COLUMN refund_arn TYPE VARCHAR(128);
+
+ALTER TABLE reverse_lookup
+    ALTER COLUMN lookup_id TYPE VARCHAR(128),
+    ALTER COLUMN sk_id TYPE VARCHAR(128),
+    ALTER COLUMN pk_id TYPE VARCHAR(128),
+    ALTER COLUMN source TYPE VARCHAR(128);
+
+
+
+-- File: migrations/2022-12-21-071825_add_refund_reason/up.sql
+ALTER TABLE REFUND ADD COLUMN refund_reason VARCHAR(255) DEFAULT NULL;
+
+
+
+-- File: migrations/2022-12-21-124904_remove_metadata_default_as_null/up.sql
+ALTER TABLE payment_intent ALTER COLUMN metadata DROP DEFAULT;
+
+
+-- File: migrations/2022-12-22-091431_attempt_status_rename/up.sql
+ALTER TYPE "AttemptStatus" RENAME VALUE 'juspay_declined' TO 'router_declined';
+ALTER TYPE "AttemptStatus" RENAME VALUE 'pending_vbv' TO 'authentication_successful';
+ALTER TYPE "AttemptStatus" RENAME VALUE 'vbv_successful' TO 'authentication_pending';
+
+
+
+-- File: migrations/2022-12-27-172643_update_locker_mock_up/up.sql
+-- Your SQL goes here
+ALTER TABLE locker_mock_up
+ADD COLUMN payment_method_id VARCHAR(64);
+
+
+-- File: migrations/2023-01-03-122401_update_merchant_account/up.sql
+-- Your SQL goes here
+ALTER TABLE merchant_account
+ADD COLUMN locker_id VARCHAR(64);
+
+
+-- File: migrations/2023-01-10-035412_connector-metadata-payment-attempt/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_attempt ADD COLUMN connector_metadata JSONB DEFAULT NULL;
+
+
+-- File: migrations/2023-01-11-134448_add_metadata_to_merchant_account/up.sql
+-- Your SQL goes here
+ALTER TABLE merchant_account ADD COLUMN metadata JSONB DEFAULT NULL;
+
+
+-- File: migrations/2023-01-12-084710_update_merchant_routing_algorithm/up.sql
+-- Your SQL goes here
+ALTER TABLE merchant_account DROP COLUMN routing_algorithm;
+ALTER TABLE merchant_account DROP COLUMN custom_routing_rules;
+ALTER TABLE merchant_account ADD COLUMN routing_algorithm JSON;
+DROP TYPE "RoutingAlgorithm";
+
+
+
+-- File: migrations/2023-01-12-140107_drop_temp_card/up.sql
+DROP TABLE temp_card;
+
+
+
+-- File: migrations/2023-01-19-122511_add_refund_error_code/up.sql
+ALTER TABLE refund
+ADD IF NOT EXISTS refund_error_code TEXT DEFAULT NULL;
+
+
+
+-- File: migrations/2023-01-20-113235_add_attempt_id_to_payment_intent/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_intent ADD COLUMN active_attempt_id VARCHAR(64) NOT NULL DEFAULT 'xxx';
+
+UPDATE payment_intent SET active_attempt_id = payment_attempt.attempt_id from payment_attempt where payment_intent.active_attempt_id = payment_attempt.payment_id;
+
+CREATE UNIQUE INDEX payment_attempt_payment_id_merchant_id_attempt_id_index ON payment_attempt (payment_id, merchant_id, attempt_id);
+
+-- Because payment_attempt table can have rows with same payment_id and merchant_id, this index is dropped.
+DROP index payment_attempt_payment_id_merchant_id_index;
+
+CREATE INDEX payment_attempt_payment_id_merchant_id_index ON payment_attempt (payment_id, merchant_id);
+
+
+
+-- File: migrations/2023-02-01-135102_create_api_keys_table/up.sql
+CREATE TABLE api_keys (
+    key_id VARCHAR(64) NOT NULL PRIMARY KEY,
+    merchant_id VARCHAR(64) NOT NULL,
+    NAME VARCHAR(64) NOT NULL,
+    description VARCHAR(256) DEFAULT NULL,
+    hash_key VARCHAR(64) NOT NULL,
+    hashed_api_key VARCHAR(128) NOT NULL,
+    prefix VARCHAR(16) NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP,
+    expires_at TIMESTAMP DEFAULT NULL,
+    last_used TIMESTAMP DEFAULT NULL
+);
+
+
+
+-- File: migrations/2023-02-02-055700_add_payment_issuer_and_experience_in_payment_attempt/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_attempt
+ADD COLUMN IF NOT EXISTS payment_issuer VARCHAR(50);
+
+ALTER TABLE payment_attempt
+ADD COLUMN IF NOT EXISTS payment_experience VARCHAR(50);
+
+
+
+-- File: migrations/2023-02-02-062215_remove_redirect_and_payment_flow_from_payment_attempt/up.sql
+ALTER TABLE payment_attempt DROP COLUMN IF EXISTS redirect;
+
+ALTER TABLE payment_attempt DROP COLUMN IF EXISTS payment_flow;
+
+DROP TYPE IF EXISTS "PaymentFlow";
+
+
+
+-- File: migrations/2023-02-07-070512_change_merchant_connector_id_data_type/up.sql
+ALTER TABLE merchant_connector_account
+ALTER COLUMN merchant_connector_id TYPE VARCHAR(128) USING merchant_connector_id::varchar;
+
+
+ALTER TABLE merchant_connector_account
+ALTER COLUMN merchant_connector_id DROP DEFAULT;
+
+
+
+-- File: migrations/2023-02-09-093400_add_bank_redirect/up.sql
+-- Your SQL goes here
+ALTER TYPE "PaymentMethodType" ADD VALUE 'bank_redirect' after 'paypal';
+
+
+
+-- File: migrations/2023-02-10-083146_make_payment_method_type_as_text/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_methods
+ALTER COLUMN payment_method_type TYPE VARCHAR(64);
+
+ALTER TABLE payment_attempt
+ADD COLUMN payment_method_type VARCHAR(64);
+
+DROP TYPE IF EXISTS "PaymentMethodSubType";
+
+
+
+-- File: migrations/2023-02-20-101809_update_merchant_connector_account/up.sql
+ALTER TABLE merchant_connector_account
+ADD COLUMN connector_label VARCHAR(255),
+    ADD COLUMN business_country VARCHAR(2) DEFAULT 'US' NOT NULL,
+    ADD COLUMN business_label VARCHAR(255) DEFAULT 'default' NOT NULL;
+
+-- To backfill, use `US` as default country and `default` as the business_label
+UPDATE merchant_connector_account AS m
+SET connector_label = concat(
+        m.connector_name,
+        '_',
+        'US',
+        '_',
+        'default'
+    );
+
+ALTER TABLE merchant_connector_account
+ALTER COLUMN connector_label
+SET NOT NULL,
+    ALTER COLUMN business_country DROP DEFAULT,
+    ALTER COLUMN business_label DROP DEFAULT;
+
+DROP INDEX merchant_connector_account_merchant_id_connector_name_index;
+
+CREATE UNIQUE INDEX merchant_connector_account_merchant_id_connector_label_index ON merchant_connector_account (merchant_id, connector_label);
+
+
+
+-- File: migrations/2023-02-21-065628_update_merchant_account/up.sql
+ALTER TABLE merchant_account
+ADD COLUMN IF NOT EXISTS primary_business_details JSON NOT NULL DEFAULT '{"country": ["US"], "business": ["default"]}';
+
+
+
+-- File: migrations/2023-02-21-094019_api_keys_remove_hash_key/up.sql
+ALTER TABLE api_keys DROP COLUMN hash_key;
+
+/*
+ Once we've dropped the `hash_key` column, we cannot use the existing API keys
+ from the `api_keys` table anymore, as the `hash_key` is a random string that
+ we no longer have.
+ */
+TRUNCATE TABLE api_keys;
+
+ALTER TABLE api_keys
+ADD CONSTRAINT api_keys_hashed_api_key_key UNIQUE (hashed_api_key);
+
+
+
+-- File: migrations/2023-02-22-100331_rename_pm_type_enum/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_attempt
+ALTER COLUMN payment_method TYPE VARCHAR;
+
+ALTER TABLE payment_methods
+ALTER COLUMN payment_method TYPE VARCHAR;
+
+ALTER TABLE payment_methods
+ALTER COLUMN payment_method_type TYPE VARCHAR;
+
+ALTER TABLE payment_attempt DROP COLUMN payment_issuer;
+
+ALTER TABLE payment_attempt
+ADD COLUMN payment_method_data JSONB;
+
+DROP TYPE "PaymentMethodType";
+
+
+
+-- File: migrations/2023-02-28-072631_ang-currency/up.sql
+-- Your SQL goes here
+ALTER TYPE "Currency" ADD VALUE 'ANG' after 'AMD';
+
+
+
+-- File: migrations/2023-02-28-112730_add_refund_webhook_types/up.sql
+-- Your SQL goes here
+ALTER TYPE "EventClass" ADD VALUE 'refunds';
+
+ALTER TYPE "EventObjectType" ADD VALUE 'refund_details';
+
+ALTER TYPE "EventType" ADD VALUE 'refund_succeeded';
+
+ALTER TYPE "EventType" ADD VALUE 'refund_failed';
+
+
+-- File: migrations/2023-03-04-114058_remove_api_key_column_merchant_account_table/up.sql
+ALTER TABLE merchant_account DROP COLUMN api_key;
+
+
+
+-- File: migrations/2023-03-07-141638_make_payment_attempt_connector_json/up.sql
+-- Alter column type to json
+-- as well as the connector.
+ALTER TABLE payment_attempt
+ALTER COLUMN connector TYPE JSONB
+USING jsonb_build_object(
+    'routed_through', connector,
+    'algorithm',      NULL
+);
+
+
+
+-- File: migrations/2023-03-14-123541_add_cards_info_table/up.sql
+-- Your SQL goes here
+CREATE TABLE cards_info (
+    card_iin VARCHAR(16) PRIMARY KEY,
+    card_issuer TEXT,
+    card_network TEXT,
+    card_type TEXT,
+    card_subtype TEXT,
+    card_issuing_country TEXT,
+    bank_code_id VARCHAR(32),
+    bank_code VARCHAR(32),
+    country_code VARCHAR(32),
+    date_created TIMESTAMP NOT NULL,
+    last_updated TIMESTAMP,
+    last_updated_provider TEXT
+);
+
+
+
+-- File: migrations/2023-03-15-082312_add_connector_txn_id_merchant_id_index_in_payment_attempt/up.sql
+-- Your SQL goes here
+CREATE INDEX payment_attempt_connector_transaction_id_merchant_id_index ON payment_attempt (connector_transaction_id, merchant_id);
+
+
+
+-- File: migrations/2023-03-15-185959_add_dispute_table/up.sql
+CREATE TYPE "DisputeStage" AS ENUM ('pre_dispute', 'dispute', 'pre_arbitration');
+
+CREATE TYPE "DisputeStatus" AS ENUM ('dispute_opened', 'dispute_expired', 'dispute_accepted', 'dispute_cancelled', 'dispute_challenged', 'dispute_won', 'dispute_lost');
+
+CREATE TABLE dispute (
+    id SERIAL PRIMARY KEY,
+    dispute_id VARCHAR(64) NOT NULL,
+    amount VARCHAR(255) NOT NULL,
+    currency VARCHAR(255) NOT NULL,
+    dispute_stage "DisputeStage" NOT NULL,
+    dispute_status "DisputeStatus" NOT NULL,
+    payment_id VARCHAR(255) NOT NULL,
+    attempt_id VARCHAR(64) NOT NULL,
+    merchant_id VARCHAR(255) NOT NULL,
+    connector_status VARCHAR(255) NOT NULL,
+    connector_dispute_id VARCHAR(255) NOT NULL,
+    connector_reason VARCHAR(255),
+    connector_reason_code VARCHAR(255),
+    challenge_required_by VARCHAR(255),
+    dispute_created_at VARCHAR(255),
+    updated_at VARCHAR(255),
+    created_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP,
+    modified_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP
+);
+
+CREATE UNIQUE INDEX merchant_id_dispute_id_index ON dispute (merchant_id, dispute_id);
+
+CREATE UNIQUE INDEX merchant_id_payment_id_connector_dispute_id_index ON dispute (merchant_id, payment_id, connector_dispute_id);
+
+CREATE INDEX dispute_status_index ON dispute (dispute_status);
+
+CREATE INDEX dispute_stage_index ON dispute (dispute_stage);
+
+ALTER TYPE "EventClass" ADD VALUE 'disputes';
+
+ALTER TYPE "EventObjectType" ADD VALUE 'dispute_details';
+
+ALTER TYPE "EventType" ADD VALUE 'dispute_opened';
+ALTER TYPE "EventType" ADD VALUE 'dispute_expired';
+ALTER TYPE "EventType" ADD VALUE 'dispute_accepted';
+ALTER TYPE "EventType" ADD VALUE 'dispute_cancelled';
+ALTER TYPE "EventType" ADD VALUE 'dispute_challenged';
+ALTER TYPE "EventType" ADD VALUE 'dispute_won';
+ALTER TYPE "EventType" ADD VALUE 'dispute_lost';
+
+
+
+-- File: migrations/2023-03-16-105114_add_data_collection_status/up.sql
+ALTER TYPE "AttemptStatus" ADD VALUE IF NOT EXISTS 'device_data_collection_pending';
+
+
+-- File: migrations/2023-03-23-095309_add_business_sub_label_to_mca/up.sql
+ALTER TABLE merchant_connector_account
+ADD COLUMN IF NOT EXISTS business_sub_label VARCHAR(64) DEFAULT 'default';
+
+
+
+-- File: migrations/2023-03-23-123920_add_business_label_and_country_to_pi/up.sql
+ALTER TABLE payment_intent
+ADD COLUMN IF NOT EXISTS business_country VARCHAR(2) NOT NULL DEFAULT 'US',
+    ADD COLUMN IF NOT EXISTS business_label VARCHAR(64) NOT NULL DEFAULT 'default';
+
+
+
+-- File: migrations/2023-03-26-163105_add_unresolved_status/up.sql
+ALTER TYPE "AttemptStatus" ADD VALUE IF NOT EXISTS 'unresolved';
+ALTER TYPE "IntentStatus" ADD VALUE IF NOT EXISTS 'requires_merchant_action' after 'requires_customer_action';
+ALTER TYPE "EventType" ADD VALUE IF NOT EXISTS 'action_required';
+ALTER TYPE "EventType" ADD VALUE IF NOT EXISTS 'payment_processing';
+
+
+
+-- File: migrations/2023-03-27-091611_change_country_to_enum/up.sql
+CREATE TYPE "CountryCode" AS ENUM (
+    'AF',
+    'AX',
+    'AL',
+    'DZ',
+    'AS',
+    'AD',
+    'AO',
+    'AI',
+    'AQ',
+    'AG',
+    'AR',
+    'AM',
+    'AW',
+    'AU',
+    'AT',
+    'AZ',
+    'BS',
+    'BH',
+    'BD',
+    'BB',
+    'BY',
+    'BE',
+    'BZ',
+    'BJ',
+    'BM',
+    'BT',
+    'BO',
+    'BQ',
+    'BA',
+    'BW',
+    'BV',
+    'BR',
+    'IO',
+    'BN',
+    'BG',
+    'BF',
+    'BI',
+    'KH',
+    'CM',
+    'CA',
+    'CV',
+    'KY',
+    'CF',
+    'TD',
+    'CL',
+    'CN',
+    'CX',
+    'CC',
+    'CO',
+    'KM',
+    'CG',
+    'CD',
+    'CK',
+    'CR',
+    'CI',
+    'HR',
+    'CU',
+    'CW',
+    'CY',
+    'CZ',
+    'DK',
+    'DJ',
+    'DM',
+    'DO',
+    'EC',
+    'EG',
+    'SV',
+    'GQ',
+    'ER',
+    'EE',
+    'ET',
+    'FK',
+    'FO',
+    'FJ',
+    'FI',
+    'FR',
+    'GF',
+    'PF',
+    'TF',
+    'GA',
+    'GM',
+    'GE',
+    'DE',
+    'GH',
+    'GI',
+    'GR',
+    'GL',
+    'GD',
+    'GP',
+    'GU',
+    'GT',
+    'GG',
+    'GN',
+    'GW',
+    'GY',
+    'HT',
+    'HM',
+    'VA',
+    'HN',
+    'HK',
+    'HU',
+    'IS',
+    'IN',
+    'ID',
+    'IR',
+    'IQ',
+    'IE',
+    'IM',
+    'IL',
+    'IT',
+    'JM',
+    'JP',
+    'JE',
+    'JO',
+    'KZ',
+    'KE',
+    'KI',
+    'KP',
+    'KR',
+    'KW',
+    'KG',
+    'LA',
+    'LV',
+    'LB',
+    'LS',
+    'LR',
+    'LY',
+    'LI',
+    'LT',
+    'LU',
+    'MO',
+    'MK',
+    'MG',
+    'MW',
+    'MY',
+    'MV',
+    'ML',
+    'MT',
+    'MH',
+    'MQ',
+    'MR',
+    'MU',
+    'YT',
+    'MX',
+    'FM',
+    'MD',
+    'MC',
+    'MN',
+    'ME',
+    'MS',
+    'MA',
+    'MZ',
+    'MM',
+    'NA',
+    'NR',
+    'NP',
+    'NL',
+    'NC',
+    'NZ',
+    'NI',
+    'NE',
+    'NG',
+    'NU',
+    'NF',
+    'MP',
+    'NO',
+    'OM',
+    'PK',
+    'PW',
+    'PS',
+    'PA',
+    'PG',
+    'PY',
+    'PE',
+    'PH',
+    'PN',
+    'PL',
+    'PT',
+    'PR',
+    'QA',
+    'RE',
+    'RO',
+    'RU',
+    'RW',
+    'BL',
+    'SH',
+    'KN',
+    'LC',
+    'MF',
+    'PM',
+    'VC',
+    'WS',
+    'SM',
+    'ST',
+    'SA',
+    'SN',
+    'RS',
+    'SC',
+    'SL',
+    'SG',
+    'SX',
+    'SK',
+    'SI',
+    'SB',
+    'SO',
+    'ZA',
+    'GS',
+    'SS',
+    'ES',
+    'LK',
+    'SD',
+    'SR',
+    'SJ',
+    'SZ',
+    'SE',
+    'CH',
+    'SY',
+    'TW',
+    'TJ',
+    'TZ',
+    'TH',
+    'TL',
+    'TG',
+    'TK',
+    'TO',
+    'TT',
+    'TN',
+    'TR',
+    'TM',
+    'TC',
+    'TV',
+    'UG',
+    'UA',
+    'AE',
+    'GB',
+    'US',
+    'UM',
+    'UY',
+    'UZ',
+    'VU',
+    'VE',
+    'VN',
+    'VG',
+    'VI',
+    'WF',
+    'EH',
+    'YE',
+    'ZM',
+    'ZW'
+);
+
+ALTER TABLE address
+ALTER COLUMN country TYPE "CountryCode" USING country::"CountryCode";
+
+
+
+-- File: migrations/2023-03-30-132338_add_start_end_date_for_mandates/up.sql
+ALTER TABLE mandate
+ADD IF NOT EXISTS start_date TIMESTAMP NULL,
+ADD IF NOT EXISTS end_date TIMESTAMP NULL,
+ADD COLUMN metadata JSONB DEFAULT NULL;
+
+
+-- File: migrations/2023-04-03-082335_update_mca_frm_configs/up.sql
+ALTER TABLE "merchant_connector_account" ADD COLUMN frm_configs jsonb;
+
+
+-- File: migrations/2023-04-04-061926_add_dispute_api_schema/up.sql
+-- Your SQL goes here
+CREATE TABLE file_metadata (
+    file_id VARCHAR(64) NOT NULL,
+    merchant_id VARCHAR(255) NOT NULL,
+    file_name VARCHAR(255),
+    file_size INTEGER NOT NULL,
+    file_type VARCHAR(255) NOT NULL,
+    provider_file_id VARCHAR(255),
+    file_upload_provider VARCHAR(255),
+    available BOOLEAN NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP,
+    PRIMARY KEY (file_id, merchant_id)
+);
+
+
+
+-- File: migrations/2023-04-05-051523_add_business_sub_label_to_payment_attempt/up.sql
+ALTER TABLE payment_attempt
+ADD COLUMN IF NOT EXISTS business_sub_label VARCHAR(64);
+
+
+
+-- File: migrations/2023-04-05-121040_alter_mca_change_country_to_enum/up.sql
+ALTER TABLE merchant_connector_account
+ALTER COLUMN business_country TYPE "CountryCode" USING business_country::"CountryCode";
+
+
+
+-- File: migrations/2023-04-05-121047_alter_pi_change_country_to_enum/up.sql
+ALTER TABLE payment_intent
+ALTER COLUMN business_country DROP DEFAULT,
+    ALTER COLUMN business_country TYPE "CountryCode" USING business_country::"CountryCode";
+
+
+
+-- File: migrations/2023-04-06-063047_add_connector_col_in_dispute/up.sql
+-- Your SQL goes here
+ALTER TABLE dispute
+ADD COLUMN connector VARCHAR(255) NOT NULL;
+
+
+-- File: migrations/2023-04-06-092008_create_merchant_ek/up.sql
+CREATE TABLE merchant_key_store(
+    merchant_id VARCHAR(255) NOT NULL PRIMARY KEY,
+    key bytea NOT NULL,
+    created_at TIMESTAMP NOT NULL
+);
+
+-- File: migrations/2023-04-11-084958_pii-migration/up.sql
+-- Your SQL goes here
+ALTER TABLE merchant_connector_account
+    ALTER COLUMN connector_account_details TYPE bytea
+    USING convert_to(connector_account_details::text, 'UTF8');
+
+ALTER TABLE merchant_account
+    ALTER COLUMN merchant_name TYPE bytea USING convert_to(merchant_name, 'UTF8'),
+    ALTER merchant_details TYPE bytea USING convert_to(merchant_details::text, 'UTF8');
+
+ALTER TABLE address
+    ALTER COLUMN line1 TYPE bytea USING convert_to(line1, 'UTF8'),
+    ALTER COLUMN line2 TYPE bytea USING convert_to(line2, 'UTF8'),
+    ALTER COLUMN line3 TYPE bytea USING convert_to(line3, 'UTF8'),
+    ALTER COLUMN state TYPE bytea USING convert_to(state, 'UTF8'),
+    ALTER COLUMN zip TYPE bytea USING convert_to(zip, 'UTF8'),
+    ALTER COLUMN first_name TYPE bytea USING convert_to(first_name, 'UTF8'),
+    ALTER COLUMN last_name TYPE bytea USING convert_to(last_name, 'UTF8'),
+    ALTER COLUMN phone_number TYPE bytea USING convert_to(phone_number, 'UTF8');
+
+ALTER TABLE customers
+    ALTER COLUMN name TYPE bytea USING convert_to(name, 'UTF8'),
+    ALTER COLUMN email TYPE bytea USING convert_to(email, 'UTF8'),
+    ALTER COLUMN phone TYPE bytea USING convert_to(phone, 'UTF8');
+
+
+
+-- File: migrations/2023-04-12-075449_separate_payment_attempt_algorithm_col/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_attempt
+ADD COLUMN straight_through_algorithm JSONB;
+
+UPDATE payment_attempt SET straight_through_algorithm = connector->'algorithm'
+WHERE connector->>'algorithm' IS NOT NULL;
+
+ALTER TABLE payment_attempt
+ALTER COLUMN connector TYPE VARCHAR(64)
+USING connector->>'routed_through';
+
+
+
+-- File: migrations/2023-04-13-094917_change_primary_business_type/up.sql
+-- This change will allow older merchant accounts to be used with new changes
+UPDATE merchant_account
+SET primary_business_details = '[{"country": "US", "business": "default"}]';
+
+-- Since this field is optional, default is not required
+ALTER TABLE merchant_connector_account
+ALTER COLUMN business_sub_label DROP DEFAULT;
+
+
+
+-- File: migrations/2023-04-19-072152_merchant_account_add_intent_fulfilment_time/up.sql
+ALTER TABLE merchant_account ADD COLUMN IF NOT EXISTS intent_fulfillment_time BIGINT;
+
+
+
+-- File: migrations/2023-04-19-120503_update_customer_connector_customer/up.sql
+-- Your SQL goes here
+ALTER TABLE customers
+ADD COLUMN connector_customer JSONB;
+
+
+-- File: migrations/2023-04-19-120735_add_time_for_tables/up.sql
+-- Your SQL goes here
+ALTER TABLE merchant_account
+ADD COLUMN IF NOT EXISTS created_at TIMESTAMP NOT NULL DEFAULT now(),
+ADD COLUMN IF NOT EXISTS modified_at TIMESTAMP NOT NULL DEFAULT now();
+
+ALTER TABLE merchant_connector_account
+ADD COLUMN IF NOT EXISTS created_at TIMESTAMP NOT NULL DEFAULT now(),
+ADD COLUMN IF NOT EXISTS modified_at TIMESTAMP NOT NULL DEFAULT now();
+
+
+ALTER TABLE customers
+ADD COLUMN IF NOT EXISTS modified_at TIMESTAMP NOT NULL DEFAULT now();
+
+
+
+-- File: migrations/2023-04-20-073704_allow_multiple_mandate_ids/up.sql
+ALTER TABLE mandate
+    ADD COLUMN connector_mandate_ids jsonb;
+UPDATE mandate SET connector_mandate_ids = jsonb_build_object(
+            'mandate_id', connector_mandate_id,
+            'payment_method_id', NULL
+        );
+
+
+-- File: migrations/2023-04-20-162755_add_preprocessing_step_id_payment_attempt/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_attempt ADD COLUMN preprocessing_step_id VARCHAR DEFAULT NULL;
+CREATE INDEX preprocessing_step_id_index ON payment_attempt (preprocessing_step_id);
+
+
+
+-- File: migrations/2023-04-21-100150_create_index_for_api_keys/up.sql
+CREATE UNIQUE INDEX api_keys_merchant_id_key_id_index ON api_keys (merchant_id, key_id);
+
+
+-- File: migrations/2023-04-25-061159_rename_country_code_to_country_alpha2/up.sql
+-- Your SQL goes here
+ALTER TYPE "CountryCode" RENAME TO "CountryAlpha2";
+
+
+-- File: migrations/2023-04-25-091017_merchant_account_add_frm_routing_algorithm.sql/up.sql
+
+ALTER TABLE merchant_account
+ADD COLUMN frm_routing_algorithm JSONB NULL;
+
+
+-- File: migrations/2023-04-25-141011_add_connector_label_col_in_file_metadata/up.sql
+-- Your SQL goes here
+ALTER TABLE file_metadata
+ADD COLUMN connector_label VARCHAR(255);
+
+
+-- File: migrations/2023-04-26-062424_alter_dispute_table/up.sql
+ALTER TABLE dispute
+ALTER COLUMN challenge_required_by TYPE TIMESTAMP USING dispute_created_at::TIMESTAMP,
+ALTER COLUMN dispute_created_at TYPE TIMESTAMP USING dispute_created_at::TIMESTAMP,
+ALTER COLUMN updated_at TYPE TIMESTAMP USING dispute_created_at::TIMESTAMP;
+
+
+-- File: migrations/2023-04-26-090005_remove_default_created_at_modified_at/up.sql
+-- Merchant Account
+ALTER TABLE merchant_account
+ALTER COLUMN modified_at DROP DEFAULT;
+
+ALTER TABLE merchant_account
+ALTER COLUMN created_at DROP DEFAULT;
+
+
+-- Merchant Connector Account
+ALTER TABLE merchant_connector_account
+ALTER COLUMN modified_at DROP DEFAULT;
+
+ALTER TABLE merchant_connector_account
+ALTER COLUMN created_at DROP DEFAULT;
+
+-- Customers
+ALTER TABLE customers
+ALTER COLUMN modified_at DROP DEFAULT;
+
+ALTER TABLE customers
+ALTER COLUMN created_at DROP DEFAULT;
+
+-- Address
+ALTER TABLE address
+ALTER COLUMN modified_at DROP DEFAULT;
+
+ALTER TABLE address
+ALTER COLUMN created_at DROP DEFAULT;
+
+-- Refunds
+ALTER TABLE refund
+ALTER COLUMN modified_at DROP DEFAULT;
+
+ALTER TABLE refund
+ALTER COLUMN created_at DROP DEFAULT;
+
+-- Connector Response
+ALTER TABLE connector_response
+ALTER COLUMN modified_at DROP DEFAULT;
+
+ALTER TABLE connector_response
+ALTER COLUMN created_at DROP DEFAULT;
+
+-- Payment methods
+ALTER TABLE payment_methods
+ALTER COLUMN created_at DROP DEFAULT;
+
+-- Payment Intent
+ALTER TABLE payment_intent
+ALTER COLUMN modified_at DROP DEFAULT;
+
+ALTER TABLE payment_intent
+ALTER COLUMN created_at DROP DEFAULT;
+
+--- Payment Attempt
+ALTER TABLE payment_attempt
+ALTER COLUMN modified_at DROP DEFAULT;
+
+ALTER TABLE payment_attempt
+ALTER COLUMN created_at DROP DEFAULT;
+
+
+
+-- File: migrations/2023-04-27-120010_add_payment_failed_event_type/up.sql
+ALTER TYPE "EventType" ADD VALUE IF NOT EXISTS 'payment_failed';
+
+
+-- File: migrations/2023-05-02-102332_payout_create/up.sql
+CREATE type "PayoutStatus" AS ENUM (
+    'success',
+    'failed',
+    'cancelled',
+    'pending',
+    'ineligible',
+    'requires_creation',
+    'requires_payout_method_data',
+    'requires_fulfillment'
+);
+
+CREATE type "PayoutType" AS ENUM ('card', 'bank');
+
+CREATE TABLE
+    PAYOUT_ATTEMPT (
+        payout_attempt_id VARCHAR (64) NOT NULL PRIMARY KEY,
+        payout_id VARCHAR (64) NOT NULL,
+        customer_id VARCHAR (64) NOT NULL,
+        merchant_id VARCHAR (64) NOT NULL,
+        address_id VARCHAR (64) NOT NULL,
+        connector VARCHAR (64) NOT NULL,
+        connector_payout_id VARCHAR (128) NOT NULL,
+        payout_token VARCHAR (64),
+        status "PayoutStatus" NOT NULL,
+        is_eligible BOOLEAN,
+        error_message TEXT,
+        error_code VARCHAR (64),
+        business_country "CountryAlpha2",
+        business_label VARCHAR(64),
+        created_at timestamp NOT NULL DEFAULT NOW():: timestamp,
+        last_modified_at timestamp NOT NULL DEFAULT NOW():: timestamp
+    );
+
+CREATE TABLE
+    PAYOUTS (
+        payout_id VARCHAR (64) NOT NULL PRIMARY KEY,
+        merchant_id VARCHAR (64) NOT NULL,
+        customer_id VARCHAR (64) NOT NULL,
+        address_id VARCHAR (64) NOT NULL,
+        payout_type "PayoutType" NOT NULL,
+        payout_method_id VARCHAR (64),
+        amount BIGINT NOT NULL,
+        destination_currency "Currency" NOT NULL,
+        source_currency "Currency" NOT NULL,
+        description VARCHAR (255),
+        recurring BOOLEAN NOT NULL,
+        auto_fulfill BOOLEAN NOT NULL,
+        return_url VARCHAR (255),
+        entity_type VARCHAR (64) NOT NULL,
+        metadata JSONB DEFAULT '{}':: JSONB,
+        created_at timestamp NOT NULL DEFAULT NOW():: timestamp,
+        last_modified_at timestamp NOT NULL DEFAULT NOW():: timestamp
+    );
+
+CREATE UNIQUE INDEX payout_attempt_index ON PAYOUT_ATTEMPT (
+    merchant_id,
+    payout_attempt_id,
+    payout_id
+);
+
+CREATE UNIQUE INDEX payouts_index ON PAYOUTS (merchant_id, payout_id);
+
+-- Alterations
+
+ALTER TABLE merchant_account
+ADD
+    COLUMN payout_routing_algorithm JSONB;
+
+ALTER TABLE locker_mock_up ADD COLUMN enc_card_data TEXT;
+
+ALTER TYPE "ConnectorType" ADD VALUE 'payout_processor';
+
+
+-- File: migrations/2023-05-03-121025_nest_straight_through_col_in_payment_attempt/up.sql
+-- Your SQL goes here
+UPDATE payment_attempt
+SET straight_through_algorithm = jsonb_build_object('algorithm', straight_through_algorithm);
+
+
+
+-- File: migrations/2023-05-05-112013_add_evidence_col_in_dispute/up.sql
+-- Your SQL goes here
+ALTER TABLE dispute
+ADD COLUMN evidence JSONB NOT NULL DEFAULT '{}'::JSONB;
+
+
+-- File: migrations/2023-05-08-141907_rename_dispute_cols/up.sql
+-- Your SQL goes here
+ALTER TABLE dispute
+RENAME COLUMN dispute_created_at TO connector_created_at;
+
+ALTER TABLE dispute
+RENAME COLUMN updated_at TO connector_updated_at;
+
+
+
+-- File: migrations/2023-05-16-145008_mandate_data_in_pa/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_attempt ADD COLUMN mandate_details JSONB;
+
+
+
+-- File: migrations/2023-05-29-094747_order-details-as-a-separate-column.sql/up.sql
+ALTER TABLE payment_intent ADD COLUMN order_details jsonb[];
+
+
+-- File: migrations/2023-05-31-152153_add_connector_webhook_details_to_mca/up.sql
+-- Your SQL goes here
+ALTER TABLE merchant_connector_account
+ADD COLUMN IF NOT EXISTS connector_webhook_details JSONB DEFAULT NULL;
+
+
+-- File: migrations/2023-06-14-105035_add_reason_in_payment_attempt/up.sql
+ALTER TABLE payment_attempt
+ADD COLUMN error_reason TEXT;
+
+
+
+-- File: migrations/2023-06-16-073615_add_ron_currency_to_db/up.sql
+-- Your SQL goes here
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'RON' AFTER 'QAR';
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'TRY' AFTER 'TTD';
+
+
+
+-- File: migrations/2023-06-18-042123_add_udf_column_in_payments/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_intent ADD COLUMN udf JSONB;
+
+
+
+-- File: migrations/2023-06-19-071300_merchant_key_store_shrink_merchant_id/up.sql
+ALTER TABLE merchant_key_store
+ALTER COLUMN merchant_id TYPE VARCHAR(64);
+
+
+
+-- File: migrations/2023-06-22-161131_change-type-of-frm-configs.sql/up.sql
+UPDATE merchant_connector_account set frm_configs = null ;
+
+ALTER TABLE merchant_connector_account 
+ALTER COLUMN frm_configs TYPE jsonb[]
+USING ARRAY[frm_configs]::jsonb[];
+
+UPDATE merchant_connector_account set frm_configs = null ;
+
+
+
+-- File: migrations/2023-06-26-124254_add_vnd_to_currency_enum/up.sql
+-- Your SQL goes here
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'VND' AFTER 'UZS';
+
+
+-- File: migrations/2023-06-29-094858_payment-intent-remove-udf-field/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_intent DROP COLUMN udf;
+
+
+
+-- File: migrations/2023-07-01-184850_payment-intent-add-metadata-fields/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_intent
+ADD COLUMN allowed_payment_method_types JSON,
+ADD COLUMN connector_metadata JSON,
+ADD COLUMN feature_metadata JSON;
+
+
+
+-- File: migrations/2023-07-03-093552_add_attempt_count_in_payment_intent/up.sql
+ALTER TABLE payment_intent ADD COLUMN attempt_count SMALLINT NOT NULL DEFAULT 1;
+
+UPDATE payment_intent
+SET attempt_count = payment_id_count.count
+FROM (SELECT payment_id, count(payment_id) FROM payment_attempt GROUP BY payment_id) as payment_id_count
+WHERE payment_intent.payment_id = payment_id_count.payment_id;
+
+
+
+-- File: migrations/2023-07-04-131721_add_org_id_and_org_name/up.sql
+-- Your SQL goes here
+ALTER TABLE merchant_account
+ADD COLUMN IF NOT EXISTS organization_id VARCHAR(32);
+
+
+
+-- File: migrations/2023-07-07-091223_create_captures_table/up.sql
+
+CREATE TYPE "CaptureStatus" AS ENUM (
+    'started',
+    'charged',
+    'pending',
+    'failed'
+);
+ALTER TYPE "IntentStatus" ADD VALUE If NOT EXISTS 'partially_captured' AFTER 'requires_capture';
+CREATE TABLE captures(
+    capture_id VARCHAR(64) NOT NULL PRIMARY KEY,
+    payment_id VARCHAR(64) NOT NULL,
+    merchant_id VARCHAR(64) NOT NULL,
+    status "CaptureStatus" NOT NULL,
+    amount BIGINT NOT NULL,
+    currency "Currency",
+    connector VARCHAR(255),
+    error_message VARCHAR(255),
+    error_code VARCHAR(255),
+    error_reason VARCHAR(255),
+    tax_amount BIGINT,
+    created_at TIMESTAMP NOT NULL,
+    modified_at TIMESTAMP NOT NULL,
+    authorized_attempt_id VARCHAR(64) NOT NULL,
+    connector_transaction_id VARCHAR(128),
+    capture_sequence SMALLINT NOT NULL
+);
+
+CREATE INDEX captures_merchant_id_payment_id_authorized_attempt_id_index ON captures (
+    merchant_id,
+    payment_id,
+    authorized_attempt_id
+);
+CREATE INDEX captures_connector_transaction_id_index ON captures (
+    connector_transaction_id
+);
+
+ALTER TABLE payment_attempt
+ADD COLUMN multiple_capture_count SMALLINT; --number of captures available for this payment attempt in captures table
+
+
+
+-- File: migrations/2023-07-08-134807_add_connector_response_reference_id_in_payment_intent/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_attempt ADD COLUMN IF NOT EXISTS connector_response_reference_id VARCHAR(128);
+
+
+-- File: migrations/2023-07-11-140347_add_is_recon_enabled_field_in_merchant_account/up.sql
+-- Your SQL goes here
+ALTER TABLE merchant_account ADD COLUMN "is_recon_enabled" BOOLEAN NOT NULL DEFAULT FALSE;
+
+
+-- File: migrations/2023-07-17-111427_add-fraud-check-table.sql/up.sql
+-- Your SQL goes here-- Your SQL goes here
+CREATE TYPE "FraudCheckType" AS ENUM (
+    'pre_frm',
+    'post_frm'
+);
+
+CREATE TYPE "FraudCheckStatus" AS ENUM (
+    'fraud',
+    'manual_review',
+    'pending',
+    'legit',
+    'transaction_failure'
+);
+
+CREATE TABLE fraud_check (
+    frm_id VARCHAR(64) NOT NULL UNIQUE,
+    payment_id VARCHAR(64) NOT NULL,
+    merchant_id VARCHAR(64) NOT NULL,
+    attempt_id VARCHAR(64) NOT NULL UNIQUE,
+    created_at TIMESTAMP NOT NULL DEFAULT now(),
+    frm_name VARCHAR(255) NOT NULL,
+    frm_transaction_id VARCHAR(255) UNIQUE,
+    frm_transaction_type "FraudCheckType" NOT NULL,
+    frm_status "FraudCheckStatus" NOT NULL,
+    frm_score INTEGER,
+    frm_reason JSONB,
+    frm_error VARCHAR(255),
+    payment_details JSONB,
+    metadata JSONB,
+    modified_at TIMESTAMP NOT NULL DEFAULT now(),
+
+    PRIMARY KEY (frm_id, attempt_id, payment_id, merchant_id)
+);
+
+CREATE UNIQUE INDEX frm_id_index ON fraud_check (frm_id, attempt_id, payment_id, merchant_id);
+
+
+
+-- File: migrations/2023-07-19-081050_add_zero_decimal_currencies/up.sql
+-- Your SQL goes here
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'BIF' AFTER 'BHD';
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'CLP' AFTER 'CHF';
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'DJF' AFTER 'CZK';
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'GNF' AFTER 'GMD';
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'KMF' AFTER 'KHR';
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'MGA' AFTER 'MDL';
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'PYG' AFTER 'PLN';
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'RWF' AFTER 'RUB';
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'UGX' AFTER 'TZS';
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'VUV' AFTER 'VND';
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'XAF' AFTER 'VUV';
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'XOF' AFTER 'XAF';
+ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'XPF' AFTER 'XOF';
+
+
+
+-- File: migrations/2023-07-28-111829_update_columns_to_fix_db_diff/up.sql
+ALTER TABLE dispute
+ALTER COLUMN payment_id TYPE VARCHAR(64);
+
+ALTER TABLE payment_methods
+ALTER COLUMN payment_method_type TYPE VARCHAR(64);
+
+ALTER TABLE merchant_account
+ALTER COLUMN primary_business_details DROP DEFAULT;
+
+
+-- File: migrations/2023-08-01-165717_make_event_id_unique_for_events_table/up.sql
+-- Your SQL goes here
+ALTER TABLE events
+ADD CONSTRAINT event_id_unique UNIQUE (event_id);
+
+
+
+-- File: migrations/2023-08-08-144148_add_business_profile_table/up.sql
+-- Your SQL goes here
+CREATE TABLE IF NOT EXISTS business_profile (
+    profile_id VARCHAR(64) PRIMARY KEY,
+    merchant_id VARCHAR(64) NOT NULL,
+    profile_name VARCHAR(64) NOT NULL,
+    created_at TIMESTAMP NOT NULL,
+    modified_at TIMESTAMP NOT NULL,
+    return_url TEXT,
+    enable_payment_response_hash BOOLEAN NOT NULL DEFAULT TRUE,
+    payment_response_hash_key VARCHAR(255) DEFAULT NULL,
+    redirect_to_merchant_with_http_post BOOLEAN NOT NULL DEFAULT FALSE,
+    webhook_details JSON,
+    metadata JSON,
+    routing_algorithm JSON,
+    intent_fulfillment_time BIGINT,
+    frm_routing_algorithm JSONB,
+    payout_routing_algorithm JSONB,
+    is_recon_enabled BOOLEAN NOT NULL DEFAULT FALSE
+);
+
+
+
+-- File: migrations/2023-08-11-073905_add_frm_config_in_mca/up.sql
+ALTER TABLE "merchant_connector_account" ADD COLUMN frm_config jsonb[];
+-- Do not run below migration in PROD as this only makes sandbox compatible to PROD version
+ALTER TABLE merchant_connector_account 
+ALTER COLUMN frm_configs TYPE jsonb
+USING frm_configs[1]::jsonb;
+
+
+-- File: migrations/2023-08-16-080721_make_connector_field_mandatory_capture_table/up.sql
+-- Your SQL goes here
+ALTER TABLE captures ALTER COLUMN connector SET NOT NULL;
+ALTER TABLE captures RENAME COLUMN connector_transaction_id TO connector_capture_id;
+ALTER TABLE captures add COLUMN IF NOT EXISTS connector_response_reference_id VARCHAR(128);
+
+
+-- File: migrations/2023-08-16-103806_add_last_executed_frm_step/up.sql
+alter table fraud_check add column last_step VARCHAR(64) NOT NULL DEFAULT 'processing';
+
+
+-- File: migrations/2023-08-16-112847_add_profile_id_in_affected_tables/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_intent
+ADD COLUMN IF NOT EXISTS profile_id VARCHAR(64);
+
+ALTER TABLE merchant_connector_account
+ADD COLUMN IF NOT EXISTS profile_id VARCHAR(64);
+
+ALTER TABLE merchant_account
+ADD COLUMN IF NOT EXISTS default_profile VARCHAR(64);
+
+-- Profile id is needed in refunds for listing refunds by business profile
+ALTER TABLE refund
+ADD COLUMN IF NOT EXISTS profile_id VARCHAR(64);
+
+-- For listing disputes by business profile
+ALTER TABLE dispute
+ADD COLUMN IF NOT EXISTS profile_id VARCHAR(64);
+
+-- For a similar use case as to payments
+ALTER TABLE payout_attempt
+ADD COLUMN IF NOT EXISTS profile_id VARCHAR(64);
+
+
+
+-- File: migrations/2023-08-23-090712_payment_attempt_perf_idx/up.sql
+-- Your SQL goes here
+CREATE INDEX payment_attempt_attempt_id_merchant_id_index ON payment_attempt (attempt_id, merchant_id);
+
+
+
+
+-- File: migrations/2023-08-24-095037_add_profile_id_in_file_metadata/up.sql
+-- Your SQL goes here
+ALTER TABLE file_metadata
+ADD COLUMN IF NOT EXISTS profile_id VARCHAR(64);
+
+
+
+-- File: migrations/2023-08-25-094551_add_recon_status_in_merchant_account/up.sql
+-- Your SQL goes here
+CREATE TYPE "ReconStatus" AS ENUM ('requested','active', 'disabled','not_requested');
+ALTER TABLE merchant_account ADD recon_status "ReconStatus" NOT NULL DEFAULT "ReconStatus"('not_requested');
+
+
+-- File: migrations/2023-08-28-131238_make_business_details_optional/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_intent
+ALTER COLUMN business_country DROP NOT NULL;
+
+ALTER TABLE payment_intent
+ALTER COLUMN business_label DROP NOT NULL;
+
+ALTER TABLE merchant_connector_account
+ALTER COLUMN business_country DROP NOT NULL;
+
+ALTER TABLE merchant_connector_account
+ALTER COLUMN business_label DROP NOT NULL;
+
+ALTER TABLE merchant_connector_account
+ALTER COLUMN connector_label DROP NOT NULL;
+
+DROP INDEX IF EXISTS merchant_connector_account_merchant_id_connector_label_index;
+
+CREATE UNIQUE INDEX IF NOT EXISTS merchant_connector_account_profile_id_connector_id_index ON merchant_connector_account(profile_id, connector_name);
+
+CREATE UNIQUE INDEX IF NOT EXISTS business_profile_merchant_id_profile_name_index ON business_profile(merchant_id, profile_name);
+
+
+
+-- File: migrations/2023-08-31-093852_add_merchant_decision/up.sql
+alter table payment_intent add column merchant_decision VARCHAR(64);
+
+
+-- File: migrations/2023-09-06-101704_payment_method_data_in_payment_methods/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_methods ADD COLUMN IF NOT EXISTS payment_method_data BYTEA DEFAULT NULL;
+
+
+-- File: migrations/2023-09-07-113914_add_amount_capturable_field_payment_attempt/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_attempt
+ADD COLUMN IF NOT EXISTS amount_capturable BIGINT NOT NULL DEFAULT 0;
+
+
+-- File: migrations/2023-09-08-112817_applepay_verified_domains_in_business_profile/up.sql
+ALTER TABLE business_profile
+ADD COLUMN IF NOT EXISTS applepay_verified_domains text[];
+
+
+
+
+-- File: migrations/2023-09-08-134514_add_payment_confirm_source_in_payment_intent/up.sql
+-- Your SQL goes here
+CREATE TYPE "PaymentSource" AS ENUM (
+    'merchant_server',
+    'postman',
+    'dashboard',
+    'sdk'
+);
+
+ALTER TABLE payment_intent
+ADD COLUMN IF NOT EXISTS payment_confirm_source "PaymentSource";
+
+
+-- File: migrations/2023-09-13-075226_applepay_verified_domains_in_mca/up.sql
+ALTER TABLE merchant_connector_account
+ADD COLUMN IF NOT EXISTS applepay_verified_domains text[];
+
+
+
+-- File: migrations/2023-09-14-032447_add_payment_id_in_address/up.sql
+-- Your SQL goes here
+ALTER TABLE address ADD COLUMN payment_id VARCHAR(64);
+ALTER TABLE customers ADD COLUMN address_id VARCHAR(64);
+
+
+-- File: migrations/2023-09-17-152010_make_id_not_null_address/up.sql
+-- Your SQL goes here
+ALTER TABLE address ALTER COLUMN id DROP NOT NULL;
+
+
+-- File: migrations/2023-09-18-104900_add_pm_auth_config_mca/up.sql
+-- Your SQL goes here
+ALTER TABLE merchant_connector_account ADD COLUMN IF NOT EXISTS pm_auth_config JSONB DEFAULT NULL;
+ALTER TYPE "ConnectorType" ADD VALUE 'payment_method_auth';
+
+
+-- File: migrations/2023-09-25-125007_add_surcharge_metadata_payment_attempt/up.sql
+-- Your SQL goes here
+ALTER TABLE payment_attempt
+ADD COLUMN IF NOT EXISTS surcharge_metadata JSONB DEFAULT NULL;
+
+
+-- File: migrations/2023-10-05-085859_make_org_id_mandatory_in_ma/up.sql
+-- Your SQL goes here
+UPDATE merchant_account
+SET organization_id = 'org_abcdefghijklmn'
+WHERE organization_id IS NULL;
+
+ALTER TABLE merchant_account
+ALTER COLUMN organization_id
+SET NOT NULL;
+
+
+
+-- File: migrations/2023-10-05-114138_add_payment_id_in_mandate/up.sql
+-- Your SQL goes here
+ALTER TABLE mandate ADD COLUMN original_payment_id VARCHAR(64);
+
+
+-- File: migrations/2023-10-05-130917_add_mandate_webhook_types/up.sql
+-- Your SQL goes here
+ALTER TYPE "EventClass" ADD VALUE 'mandates';
+
+ALTER TYPE "EventObjectType" ADD VALUE 'mandate_details';
+
+ALTER TYPE "EventType" ADD VALUE 'mandate_active';
+
+ALTER TYPE "EventType" ADD VALUE 'mandate_revoked';
+
+
diff --git a/aws/hyperswitch_aws_setup.sh b/aws/hyperswitch_aws_setup.sh
new file mode 100644
index 000000000000..dd71b698e93e
--- /dev/null
+++ b/aws/hyperswitch_aws_setup.sh
@@ -0,0 +1,340 @@
+#!/bin/bash
+
+command_discovery() {
+  type $1 > /dev/null 2> /dev/null
+  if [[ $? != 0 ]]; then
+    echo "\`$1\` command not found"
+    exit 1
+  fi
+}
+
+command_discovery curl
+command_discovery aws
+command_discovery psql
+
+echo "Please enter the AWS region (us-east-2): "
+read REGION < /dev/tty
+
+if [ -z "$REGION" ]; then
+    echo "Using default region: us-east-2"
+    REGION="us-east-2"
+fi
+
+while [[ -z "$MASTER_DB_PASSWORD" ]]; do
+    echo "Please enter the password for your RDS instance: "
+    echo "Minimum length: 8 Characters [A-Z][a-z][0-9]"
+    read MASTER_DB_PASSWORD < /dev/tty
+done
+
+while [[ -z "$ADMIN_API_KEY" ]]; do
+    echo "Please configure the Admin api key: (Required to access Hyperswitch APIs)"
+    read ADMIN_API_KEY < /dev/tty
+done
+
+#############  APPLICATION ##################
+# CREATE SECURITY GROUP FOR APPLICATION
+
+echo "Creating Security Group for Application..."
+
+export EC2_SG="application-sg"
+
+echo `(aws ec2 create-security-group \
+--region $REGION \
+--group-name $EC2_SG \
+--description "Security Group for Hyperswitch EC2 instance" \
+--tag-specifications "ResourceType=security-group,Tags=[{Key=ManagedBy,Value=hyperswitch}]" \
+)`
+
+export APP_SG_ID=$(aws ec2 describe-security-groups --group-names $EC2_SG --region $REGION --output text --query 'SecurityGroups[0].GroupId')
+
+echo "Security Group for Application CREATED.\n"
+
+echo "Creating Security Group ingress for port 80..."
+
+echo `aws ec2 authorize-security-group-ingress \
+--group-id $APP_SG_ID \
+--protocol tcp \
+--port 80 \
+--cidr 0.0.0.0/0 \
+--region $REGION`
+
+echo "Security Group ingress for port 80 CREATED.\n"
+
+
+echo "Creating Security Group ingress for port 22..."
+
+echo `aws ec2 authorize-security-group-ingress \
+--group-id $APP_SG_ID \
+--protocol tcp \
+--port 22 \
+--cidr 0.0.0.0/0 \
+--region $REGION`
+
+echo "Security Group ingress for port 22 CREATED.\n"
+
+#############  REDIS ##################
+# CREATE SECURITY GROUP FOR ELASTICACHE
+
+echo "Creating Security Group for Elasticache..."
+
+export REDIS_GROUP_NAME=redis-sg
+echo `aws ec2 create-security-group \
+--group-name $REDIS_GROUP_NAME \
+--description "SG attached to elasticache" \
+--tag-specifications "ResourceType=security-group,Tags=[{Key=ManagedBy,Value=hyperswitch}]" \
+--region $REGION`
+
+echo "Security Group for Elasticache CREATED.\n"
+
+echo "Creating Inbound rules for Redis..."
+
+export REDIS_SG_ID=$(aws ec2 describe-security-groups --group-names $REDIS_GROUP_NAME --region $REGION --output text --query 'SecurityGroups[0].GroupId')
+
+# CREATE INBOUND RULES
+echo `aws ec2 authorize-security-group-ingress \
+--group-id $REDIS_SG_ID \
+--protocol tcp \
+--port 6379 \
+--source-group $EC2_SG \
+--region $REGION`
+
+echo "Inbound rules for Redis CREATED.\n"
+
+#############  DB ##################
+
+echo "Creating Security Group for RDS..."
+
+export RDS_GROUP_NAME=rds-sg
+echo `aws ec2 create-security-group \
+--group-name $RDS_GROUP_NAME \
+--description "SG attached to RDS" \
+--tag-specifications "ResourceType=security-group,Tags=[{Key=ManagedBy,Value=hyperswitch}]" \
+--region $REGION`
+
+echo "Security Group for RDS CREATED.\n"
+
+echo "Creating Inbound rules for RDS..."
+
+export RDS_SG_ID=$(aws ec2 describe-security-groups --group-names $RDS_GROUP_NAME --region $REGION --output text --query 'SecurityGroups[0].GroupId')
+
+# CREATE INBOUND RULES
+echo `aws ec2 authorize-security-group-ingress \
+--group-id $RDS_SG_ID \
+--protocol tcp \
+--port 5432 \
+--source-group $EC2_SG \
+--region $REGION`
+
+echo "Inbound rules for RDS CREATED.\n"
+
+echo `aws ec2 authorize-security-group-ingress \
+    --group-id $RDS_SG_ID \
+    --protocol tcp \
+    --port 5432 \
+    --cidr 0.0.0.0/0 \
+    --region $REGION`
+
+echo "Inbound rules for RDS (from any IP) CREATED.\n"
+
+echo "Creating Elasticache with Redis engine..."
+
+export CACHE_CLUSTER_ID=hyperswitch-cluster
+
+echo `aws elasticache create-cache-cluster \
+--cache-cluster-id $CACHE_CLUSTER_ID \
+--cache-node-type cache.t3.medium \
+--engine redis \
+--num-cache-nodes 1 \
+--security-group-ids $REDIS_SG_ID \
+--engine-version 7.0 \
+--tags "Key=ManagedBy,Value=hyperswitch" \
+--region $REGION`
+
+echo "Elasticache with Redis engine CREATED.\n"
+
+echo "Creating RDS with PSQL..."
+
+export DB_INSTANCE_ID=hyperswitch-db
+echo `aws rds create-db-instance  \
+    --db-instance-identifier $DB_INSTANCE_ID\
+    --db-instance-class db.t3.micro \
+    --engine postgres \
+    --allocated-storage 20 \
+    --master-username hyperswitch \
+    --master-user-password $MASTER_DB_PASSWORD \
+    --backup-retention-period 7 \
+    --region $REGION \
+    --db-name hyperswitch_db \
+    --tags "Key=ManagedBy,Value=hyperswitch" \
+    --vpc-security-group-ids $RDS_SG_ID`
+
+echo "RDS with PSQL CREATED.\n"
+
+echo "Downloading Hyperswitch PSQL Schema..."
+
+curl https://raw.githubusercontent.com/juspay/hyperswitch/main/aws/beta_schema.sql > schema.sql
+
+echo "Schema.sql downloaded.\n"
+
+echo "Awaiting RDS Initialization..."
+
+export RDS_STATUS=$(aws rds describe-db-instances \
+--db-instance-identifier $DB_INSTANCE_ID \
+--region $REGION \
+--query "DBInstances[0].DBInstanceStatus" \
+--output text)
+
+while [[ $RDS_STATUS != 'available' ]]; do
+    echo $RDS_STATUS
+    sleep 10
+
+    export RDS_STATUS=$(aws rds describe-db-instances \
+    --db-instance-identifier $DB_INSTANCE_ID \
+    --region $REGION \
+    --query "DBInstances[0].DBInstanceStatus" \
+    --output text)
+done
+
+echo "RDS Initialized.\n"
+
+echo "Retrieving RDS Endpoint..."
+
+export RDS_ENDPOINT=$(aws rds describe-db-instances --db-instance-identifier $DB_INSTANCE_ID --region $REGION --query "DBInstances[0].Endpoint.Address" --output text)
+
+echo "RDS Endpoint retrieved.\n"
+
+echo "Applying Schema to DB..."
+
+psql -d postgresql://hyperswitch:$MASTER_DB_PASSWORD@$RDS_ENDPOINT/hyperswitch_db -a -f schema.sql > /dev/null
+
+echo "Schema applied to DB.\n"
+
+cat << EOF > user_data.sh
+#!/bin/bash
+
+sudo yum update -y
+sudo amazon-linux-extras install docker
+sudo service docker start
+sudo usermod -a -G docker ec2-user
+
+docker pull juspaydotin/hyperswitch-router:beta
+
+curl https://raw.githubusercontent.com/juspay/hyperswitch/v1.55.0/config/development.toml > production.toml
+
+EOF
+
+echo "Awaiting Redis Initialization..."
+
+export redis_status=$(aws elasticache describe-cache-clusters \
+  --region $REGION \
+  --cache-cluster-id $CACHE_CLUSTER_ID \
+  --query 'CacheClusters[0].CacheClusterStatus' \
+  --output text)
+
+while [ $redis_status != 'available' ]
+do
+    echo "$redis_status"
+    sleep 10
+    export redis_status=$(aws elasticache describe-cache-clusters \
+        --region $REGION \
+        --cache-cluster-id $CACHE_CLUSTER_ID \
+        --query 'CacheClusters[0].CacheClusterStatus' \
+        --output text)
+done
+
+echo "Redis Initialized.\n"
+
+echo "Retrieving Redis Endpoint..."
+
+export REDIS_ENDPOINT=$(aws elasticache describe-cache-clusters \
+    --region $REGION \
+    --cache-cluster-id $CACHE_CLUSTER_ID \
+    --show-cache-node-info \
+    --query 'CacheClusters[0].CacheNodes[].Endpoint.Address' \
+    --output text)
+
+echo "Redis Endpoint retrieved.\n"
+
+echo "\n# Add redis and DB configs.\n" >> user_data.sh
+echo "cat << EOF >> .env" >> user_data.sh
+echo "ROUTER__REDIS__HOST=$REDIS_ENDPOINT" >> user_data.sh
+echo "ROUTER__MASTER_DATABASE__HOST=$RDS_ENDPOINT" >> user_data.sh
+echo "ROUTER__REPLICA_DATABASE__HOST=$RDS_ENDPOINT" >> user_data.sh
+echo "ROUTER__SERVER__HOST=0.0.0.0" >> user_data.sh
+echo "ROUTER__MASTER_DATABASE__USERNAME=hyperswitch" >> user_data.sh
+echo "ROUTER__MASTER_DATABASE__PASSWORD=$MASTER_DB_PASSWORD" >> user_data.sh
+echo "ROUTER__SERVER__BASE_URL=\$(curl ifconfig.me)" >> user_data.sh
+echo "ROUTER__SECRETS__ADMIN_API_KEY=$ADMIN_API_KEY" >> user_data.sh
+echo "EOF" >> user_data.sh
+
+echo "docker run --env-file .env -p 80:8080 -v \`pwd\`/:/local/config juspaydotin/hyperswitch-router:beta ./router -f /local/config/production.toml
+" >> user_data.sh
+
+echo "Retrieving AWS AMI ID..."
+
+export AWS_AMI_ID=$(aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-2.0.*" --query 'sort_by(Images, &CreationDate)[-1].ImageId' --output text --region $REGION)
+
+echo "AWS AMI ID retrieved.\n"
+
+echo "Creating EC2 Keypair..."
+
+rm -rf hyperswitch-keypair.pem
+
+aws ec2 create-key-pair \
+    --key-name hyperswitch-ec2-keypair \
+    --query 'KeyMaterial' \
+    --tag-specifications "ResourceType=key-pair,Tags=[{Key=ManagedBy,Value=hyperswitch}]" \
+    --region $REGION \
+    --output text > hyperswitch-keypair.pem
+
+echo "Keypair created and saved to hyperswitch-keypair.pem.\n"
+
+chmod 400 hyperswitch-keypair.pem
+
+echo "Launching EC2 Instance..."
+
+export HYPERSWITCH_INSTANCE_ID=$(aws ec2 run-instances \
+    --image-id $AWS_AMI_ID \
+    --instance-type t3.medium \
+    --key-name hyperswitch-ec2-keypair \
+    --monitoring "Enabled=false" \
+    --security-group-ids $APP_SG_ID \
+    --user-data file://./user_data.sh \
+    --query 'Instances[0].InstanceId' \
+    --output text \
+    --region $REGION)
+
+echo "EC2 instance launched.\n"
+
+echo "Add Tags to EC2 instance..."
+
+echo `aws ec2 create-tags \
+--resources $HYPERSWITCH_INSTANCE_ID \
+--tags "Key=Name,Value=hyperswitch-router" \
+--region $REGION`
+
+echo "Tag added to EC2 instance.\n"
+
+echo `aws ec2 create-tags \
+--resources $HYPERSWITCH_INSTANCE_ID \
+--tags "Key=ManagedBy,Value=hyperswitch" \
+--region $REGION`
+
+echo "ManagedBy tag added to EC2 instance.\n"
+
+echo "Retrieving the Public IP of Hyperswitch EC2 Instance..."
+export PUBLIC_HYPERSWITCH_IP=$(aws ec2 describe-instances \
+--instance-ids $HYPERSWITCH_INSTANCE_ID \
+--query "Reservations[*].Instances[*].PublicIpAddress" \
+--output=text \
+--region $REGION)
+
+health_status=null
+while [[ $health_status != 'health is good' ]]
+do
+    health_status=$(curl http://$PUBLIC_HYPERSWITCH_IP/health)
+    sleep 10
+done
+
+echo "Hurray! You can try using hyperswitch at http://$PUBLIC_HYPERSWITCH_IP"
+echo "Health endpoint: http://$PUBLIC_HYPERSWITCH_IP/health"
diff --git a/aws/hyperswitch_cleanup_setup.sh b/aws/hyperswitch_cleanup_setup.sh
new file mode 100644
index 000000000000..383f23d5bd00
--- /dev/null
+++ b/aws/hyperswitch_cleanup_setup.sh
@@ -0,0 +1,152 @@
+#!/bin/bash
+
+command_discovery() {
+  type $1 > /dev/null 2> /dev/null
+  if [[ $? != 0 ]]; then
+    echo "\`$1\` command not found"
+    exit 1
+  fi
+}
+
+yes_or_no() {
+    read response < /dev/tty
+    case $response in
+        [Yy]* ) return 0 ;;
+        [Nn]* ) return 1 ;;
+        * ) return 1 ;;
+    esac
+}
+
+command_discovery aws
+command_discovery jq
+
+echo -n "Please enter the AWS region (us-east-2): "
+read REGION < /dev/tty
+
+if [ -z "$REGION" ]; then
+    echo "Using default region: us-east-2"
+    REGION="us-east-2"
+fi
+
+export ALL_ELASTIC_CACHE=($(aws elasticache describe-cache-clusters \
+  --region $REGION \
+    --query "CacheClusters[*].ARN" --output text))
+
+for cluster_arn in $ALL_ELASTIC_CACHE; do
+    cluster_id=${cluster_arn##*:}
+
+    aws elasticache list-tags-for-resource \
+        --resource-name $cluster_arn \
+    --region $REGION \
+        --output json | jq \
+        '.TagList[] | select( [ .Key == "ManagedBy" and .Value == "hyperswitch" ] | any)' \
+        -e > /dev/null
+
+    if [[ $? -eq 0 ]]; then
+        echo -n "Delete $cluster_id (Y/n)? "
+        if yes_or_no; then
+            echo `aws elasticache delete-cache-cluster --region $REGION --cache-cluster-id $cluster_id`
+        fi
+    fi
+done
+
+export ALL_KEY_PAIRS=($(aws ec2 describe-key-pairs \
+            --filters "Name=tag:ManagedBy,Values=hyperswitch" \
+--region $REGION \
+    --query 'KeyPairs[*].KeyPairId' --output text))
+
+echo -n "Deleting ( $ALL_KEY_PAIRS ) key pairs? (Y/n)?"
+
+if yes_or_no; then
+    for KEY_ID in $ALL_KEY_PAIRS; do
+        echo `aws ec2 delete-key-pair --key-pair-id $KEY_ID --region $REGION`
+    done
+fi
+
+export ALL_INSTANCES=$(aws ec2 describe-instances \
+            --filters 'Name=tag:ManagedBy,Values=hyperswitch' 'Name=instance-state-name,Values=running' \
+--region $REGION \
+    --query 'Reservations[*].Instances[*].InstanceId' --output text)
+
+export ALL_EBS=$(aws ec2 describe-instances \
+            --filters 'Name=tag:ManagedBy,Values=hyperswitch' \
+--region $REGION \
+            --query 'Reservations[*].Instances[*].BlockDeviceMappings[*].Ebs.VolumeId' \
+    --output text)
+
+echo -n "Terminating ( $ALL_INSTANCES ) instances? (Y/n)?"
+
+if yes_or_no; then
+    for INSTANCE_ID in $ALL_INSTANCES; do
+        echo `aws ec2 terminate-instances --instance-ids $INSTANCE_ID --region $REGION`
+    done
+fi
+
+export ALL_DB_RESOURCES=($(aws rds describe-db-instances \
+--region $REGION \
+    --query 'DBInstances[*].DBInstanceArn' --output text))
+
+for resource_id in $ALL_DB_RESOURCES; do
+    aws rds list-tags-for-resource \
+        --resource-name $resource_id \
+   --region $REGION \
+        --output json | jq \
+        '.TagList[] | select( [ .Key == "ManagedBy" and .Value == "hyperswitch" ] | any )' \
+        -e > /dev/null
+
+    if [[ $? -eq 0 ]]; then
+        echo -n "Delete $resource_id (Y/n)? "
+        if yes_or_no; then
+            export DB_INSTANCE_ID=$(aws rds describe-db-instances \
+       --region $REGION \
+                --filters "Name=db-instance-id,Values=$resource_id" \
+                --query 'DBInstances[*].DBInstanceIdentifier' --output text)
+
+
+            echo -n "Create a snapshot before deleting ( $DB_INSTANCE_ID ) the database (Y/n)? "
+            if yes_or_no; then
+                echo `aws rds delete-db-instance \
+                    --db-instance-identifier $DB_INSTANCE_ID \
+   --region $REGION \
+                    --final-db-snapshot-identifier hyperswitch-db-snapshot-`date +%s``
+            else
+                echo `aws rds delete-db-instance \
+         --region $REGION \
+                    --db-instance-identifier $DB_INSTANCE_ID \
+                    --skip-final-snapshot`
+            fi
+        fi
+    fi
+done
+
+
+export ALL_SECURITY_GROUPS=$(aws ec2 describe-security-groups \
+            --filters 'Name=tag:ManagedBy,Values=hyperswitch' \
+--region $REGION \
+--query 'SecurityGroups[*].GroupId' --output json | jq .[] --raw-output)
+
+echo -n "Deleting ( $ALL_SECURITY_GROUPS ) security groups? (Y/n)?"
+
+if yes_or_no; then
+    export do_it=true
+
+    while $do_it; do
+      export do_it=false
+      for GROUP_ID in $ALL_SECURITY_GROUPS; do
+         aws ec2 delete-security-group --group-id $GROUP_ID --region $REGION
+         if [[ $? != 0 ]]; then
+          export do_it=true
+         fi
+      done
+
+      if $do_it; then
+        echo -n "Retry deleting the security group (Y/n)? "
+
+        if yes_or_no; then
+          export do_it=true
+        else
+          export do_it=false
+        fi
+      fi
+    done
+fi
diff --git a/config/config.example.toml b/config/config.example.toml
index 2494e9e472ef..6a5f184463ab 100644
--- a/config/config.example.toml
+++ b/config/config.example.toml
@@ -115,7 +115,6 @@ host = ""                      # Locker host
 mock_locker = true             # Emulate a locker locally using Postgres
 basilisk_host = ""             # Basilisk host
 locker_signing_key_id = "1"    # Key_id to sign basilisk hs locker
-redis_temp_locker_encryption_key = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"  # encryption key for redis temp locker
 
 [delayed_session_response]
 connectors_with_delayed_session_response = "trustpay,payme" # List of connectors which has delayed session response
@@ -164,6 +163,7 @@ airwallex.base_url = "https://api-demo.airwallex.com/"
 applepay.base_url = "https://apple-pay-gateway.apple.com/"
 authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api"
 bambora.base_url = "https://api.na.bambora.com"
+bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/"
 bitpay.base_url = "https://test.bitpay.com"
 bluesnap.base_url = "https://sandbox.bluesnap.com/"
 bluesnap.secondary_base_url = "https://sandpay.bluesnap.com/"
@@ -437,6 +437,23 @@ apple_pay_ppc_key = "APPLE_PAY_PAYMENT_PROCESSING_CERTIFICATE_KEY"      #Private
 apple_pay_merchant_cert = "APPLE_PAY_MERCHNAT_CERTIFICATE"              #Merchant Certificate provided by Apple Pay (https://developer.apple.com/) Certificates, Identifiers & Profiles > Apple Pay Merchant Identity Certificate
 apple_pay_merchant_cert_key = "APPLE_PAY_MERCHNAT_CERTIFICATE_KEY"      #Private key generate by RSA:2048 algorithm
 
-
 [payment_link]
-sdk_url = "http://localhost:9090/dist/HyperLoader.js"
\ No newline at end of file
+sdk_url = "http://localhost:9090/dist/HyperLoader.js"
+
+# Analytics configuration.
+[analytics]
+source = "sqlx" # The Analytics source/strategy to be used
+
+[analytics.sqlx]
+username = "db_user"      # Analytics DB Username
+password = "db_pass"      # Analytics DB Password
+host = "localhost"        # Analytics DB Host
+port = 5432               # Analytics DB Port
+dbname = "hyperswitch_db" # Name of Database
+pool_size = 5             # Number of connections to keep open
+connection_timeout = 10   # Timeout for database connection in seconds
+
+# Config for KV setup
+[kv_config]
+# TTL for KV in seconds
+ttl = 900
diff --git a/config/development.toml b/config/development.toml
index 8c6ae6fc80ef..17418a98643e 100644
--- a/config/development.toml
+++ b/config/development.toml
@@ -50,7 +50,6 @@ applepay_endpoint = "DOMAIN SPECIFIC ENDPOINT"
 host = ""
 mock_locker = true
 basilisk_host = ""
-redis_temp_locker_encryption_key = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
 
 [jwekey]
 locker_key_identifier1 = ""
@@ -72,6 +71,7 @@ cards = [
     "airwallex",
     "authorizedotnet",
     "bambora",
+    "bankofamerica",
     "bitpay",
     "bluesnap",
     "boku",
@@ -137,6 +137,7 @@ airwallex.base_url = "https://api-demo.airwallex.com/"
 applepay.base_url = "https://apple-pay-gateway.apple.com/"
 authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api"
 bambora.base_url = "https://api.na.bambora.com"
+bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/"
 bitpay.base_url = "https://test.bitpay.com"
 bluesnap.base_url = "https://sandbox.bluesnap.com/"
 bluesnap.secondary_base_url = "https://sandpay.bluesnap.com/"
@@ -247,7 +248,7 @@ ideal = { country = "NL", currency = "EUR" }
 [pm_filters.stripe]
 google_pay = { country = "AL,DZ,AS,AO,AG,AR,AU,AT,AZ,BH,BY,BE,BR,BG,CA,CL,CO,HR,CZ,DK,DO,EG,EE,FI,FR,DE,GR,HK,HU,IN,ID,IE,IL,IT,JP,JO,KZ,KE,KW,LV,LB,LT,LU,MY,MX,NL,NZ,NO,OM,PK,PA,PE,PH,PL,PT,QA,RO,RU,SA,SG,SK,ZA,ES,LK,SE,CH,TW,TH,TR,UA,AE,GB,US,UY,VN" }
 apple_pay = { country = "AU,CN,HK,JP,MO,MY,NZ,SG,TW,AM,AT,AZ,BY,BE,BG,HR,CY,CZ,DK,EE,FO,FI,FR,GE,DE,GR,GL,GG,HU,IS,IE,IM,IT,KZ,JE,LV,LI,LT,LU,MT,MD,MC,ME,NL,NO,PL,PT,RO,SM,RS,SK,SI,ES,SE,CH,UA,GB,AR,CO,CR,BR,MX,PE,BH,IL,JO,KW,PS,QA,SA,AE,CA,UM,US,KR,VN,MA,ZA,VA,CL,SV,GT,HN,PA" }
-klarna = { country = "US", currency = "USD" }
+klarna = { country = "AU,AT,BE,CA,CZ,DK,FI,FR,DE,GR,IE,IT,NL,NZ,NO,PL,PT,ES,SE,CH,GB,US", currency = "AUD,CAD,CHF,CZK,DKK,EUR,GBP,NOK,NZD,PLN,SEK,USD" }
 affirm = { country = "US", currency = "USD" }
 afterpay_clearpay = { country = "US,CA,GB,AU,NZ,FR,ES", currency = "USD,CAD,GBP,AUD,NZD" }
 giropay = { country = "DE", currency = "EUR" }
@@ -452,4 +453,7 @@ sdk_url = "http://localhost:9090/dist/HyperLoader.js"
 
 [lock_settings]
 redis_lock_expiry_seconds = 180 # 3 * 60 seconds
-delay_between_retries_in_milliseconds = 500
\ No newline at end of file
+delay_between_retries_in_milliseconds = 500
+
+[kv_config]
+ttl = 900 # 15 * 60 seconds
diff --git a/config/docker_compose.toml b/config/docker_compose.toml
index 0126aeec6645..ad3c3ef2f95f 100644
--- a/config/docker_compose.toml
+++ b/config/docker_compose.toml
@@ -46,7 +46,6 @@ recon_admin_api_key = "recon_test_admin"
 host = ""
 mock_locker = true
 basilisk_host = ""
-redis_temp_locker_encryption_key = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
 
 [jwekey]
 locker_key_identifier1 = ""
@@ -79,6 +78,7 @@ airwallex.base_url = "https://api-demo.airwallex.com/"
 applepay.base_url = "https://apple-pay-gateway.apple.com/"
 authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api"
 bambora.base_url = "https://api.na.bambora.com"
+bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/"
 bitpay.base_url = "https://test.bitpay.com"
 bluesnap.base_url = "https://sandbox.bluesnap.com/"
 bluesnap.secondary_base_url = "https://sandpay.bluesnap.com/"
@@ -146,6 +146,7 @@ cards = [
     "airwallex",
     "authorizedotnet",
     "bambora",
+    "bankofamerica",
     "bitpay",
     "bluesnap",
     "boku",
@@ -319,4 +320,18 @@ supported_connectors = "braintree"
 
 [lock_settings]
 redis_lock_expiry_seconds = 180 # 3 * 60 seconds
-delay_between_retries_in_milliseconds = 500
\ No newline at end of file
+delay_between_retries_in_milliseconds = 500
+
+[analytics]
+source = "sqlx"
+
+[analytics.sqlx]
+username = "db_user"
+password = "db_pass"
+host = "pg"
+port = 5432
+dbname = "hyperswitch_db"
+pool_size = 5
+
+[kv_config]
+ttl = 900 # 15 * 60 seconds
diff --git a/connector-template/mod.rs b/connector-template/mod.rs
index 05f527d24662..7f21962109de 100644
--- a/connector-template/mod.rs
+++ b/connector-template/mod.rs
@@ -105,6 +105,7 @@ impl ConnectorCommon for {{project-name | downcase | pascal_case}} {
             code: response.code,
             message: response.message,
             reason: response.reason,
+            attempt_status: None,
         })
     }
 }
@@ -156,7 +157,7 @@ impl
         Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
     }
 
-    fn get_request_body(&self, req: &types::PaymentsAuthorizeRouterData) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
+    fn get_request_body(&self, req: &types::PaymentsAuthorizeRouterData, _connectors: &settings::Connectors,) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data =
             {{project-name | downcase}}::{{project-name | downcase | pascal_case}}RouterData::try_from((
                 &self.get_currency_unit(),
@@ -185,7 +186,7 @@ impl
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(self, req, connectors)?)
                 .build(),
         ))
     }
@@ -301,6 +302,7 @@ impl
     fn get_request_body(
         &self,
         _req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into())
     }
@@ -318,7 +320,7 @@ impl
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(self, req, connectors)?)
                 .build(),
         ))
     }
@@ -373,7 +375,7 @@ impl
         Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
     }
 
-    fn get_request_body(&self, req: &types::RefundsRouterData<api::Execute>) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
+    fn get_request_body(&self, req: &types::RefundsRouterData<api::Execute>, _connectors: &settings::Connectors,) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data =
             {{project-name | downcase}}::{{project-name | downcase | pascal_case}}RouterData::try_from((
                 &self.get_currency_unit(),
@@ -393,7 +395,7 @@ impl
             .url(&types::RefundExecuteType::get_url(self, req, connectors)?)
             .attach_default_headers()
             .headers(types::RefundExecuteType::get_headers(self, req, connectors)?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(self, req, connectors)?)
             .build();
         Ok(Some(request))
     }
@@ -441,7 +443,7 @@ impl
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(self, req, connectors)?)
                 .build(),
         ))
     }
diff --git a/crates/api_models/Cargo.toml b/crates/api_models/Cargo.toml
index ce61d30d36f5..ce882e913282 100644
--- a/crates/api_models/Cargo.toml
+++ b/crates/api_models/Cargo.toml
@@ -9,8 +9,12 @@ license.workspace = true
 
 [features]
 default = ["payouts"]
+business_profile_routing = []
+connector_choice_bcompat = []
 errors = ["dep:actix-web", "dep:reqwest"]
-dummy_connector = ["common_enums/dummy_connector"]
+backwards_compatibility = ["connector_choice_bcompat"]
+connector_choice_mca_id = ["euclid/connector_choice_mca_id"]
+dummy_connector = ["euclid/dummy_connector"]
 detailed_errors = []
 payouts = []
 
@@ -21,16 +25,15 @@ mime = "0.3.17"
 reqwest = { version = "0.11.18", optional = true }
 serde = { version = "1.0.163", features = ["derive"] }
 serde_json = "1.0.96"
-serde_with = "3.0.0"
 strum = { version = "0.24.1", features = ["derive"] }
 time = { version = "0.3.21", features = ["serde", "serde-well-known", "std"] }
 url = { version = "2.4.0", features = ["serde"] }
 utoipa = { version = "3.3.0", features = ["preserve_order"] }
-thiserror = "1.0.40"
 
 # First party crates
 cards = { version = "0.1.0", path = "../cards" }
 common_enums = { path = "../common_enums" }
 common_utils = { version = "0.1.0", path = "../common_utils" }
+euclid = { version = "0.1.0", path = "../euclid" }
 masking = { version = "0.1.0", path = "../masking" }
 router_derive = { version = "0.1.0", path = "../router_derive" }
diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs
index af6a8aa446fc..979214a071a9 100644
--- a/crates/api_models/src/admin.rs
+++ b/crates/api_models/src/admin.rs
@@ -14,12 +14,12 @@ use crate::{
     payment_methods,
 };
 
-#[derive(Clone, Debug, Deserialize, ToSchema)]
+#[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
 pub struct MerchantAccountListRequest {
     pub organization_id: String,
 }
 
-#[derive(Clone, Debug, Deserialize, ToSchema)]
+#[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
 #[serde(deny_unknown_fields)]
 pub struct MerchantAccountCreate {
     /// The identifier for the Merchant Account
@@ -111,7 +111,7 @@ pub struct MerchantAccountMetadata {
     #[serde(flatten)]
     pub data: Option<pii::SecretSerdeValue>,
 }
-#[derive(Clone, Debug, Deserialize, ToSchema)]
+#[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
 #[serde(deny_unknown_fields)]
 pub struct MerchantAccountUpdate {
     /// The identifier for the Merchant Account
@@ -443,62 +443,6 @@ pub mod payout_routing_algorithm {
     }
 }
 
-#[derive(Clone, Debug, Deserialize, Serialize)]
-#[serde(tag = "type", content = "data", rename_all = "snake_case")]
-pub enum RoutingAlgorithm {
-    Single(api_enums::RoutableConnectors),
-}
-
-#[derive(Clone, Debug, Deserialize, Serialize)]
-#[serde(
-    tag = "type",
-    content = "data",
-    rename_all = "snake_case",
-    from = "StraightThroughAlgorithmSerde",
-    into = "StraightThroughAlgorithmSerde"
-)]
-pub enum StraightThroughAlgorithm {
-    Single(api_enums::RoutableConnectors),
-}
-
-#[derive(Clone, Debug, Deserialize, Serialize)]
-#[serde(tag = "type", content = "data", rename_all = "snake_case")]
-pub enum StraightThroughAlgorithmInner {
-    Single(api_enums::RoutableConnectors),
-}
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[serde(untagged)]
-pub enum StraightThroughAlgorithmSerde {
-    Direct(StraightThroughAlgorithmInner),
-    Nested {
-        algorithm: StraightThroughAlgorithmInner,
-    },
-}
-
-impl From<StraightThroughAlgorithmSerde> for StraightThroughAlgorithm {
-    fn from(value: StraightThroughAlgorithmSerde) -> Self {
-        let inner = match value {
-            StraightThroughAlgorithmSerde::Direct(algorithm) => algorithm,
-            StraightThroughAlgorithmSerde::Nested { algorithm } => algorithm,
-        };
-
-        match inner {
-            StraightThroughAlgorithmInner::Single(conn) => Self::Single(conn),
-        }
-    }
-}
-
-impl From<StraightThroughAlgorithm> for StraightThroughAlgorithmSerde {
-    fn from(value: StraightThroughAlgorithm) -> Self {
-        let inner = match value {
-            StraightThroughAlgorithm::Single(conn) => StraightThroughAlgorithmInner::Single(conn),
-        };
-
-        Self::Nested { algorithm: inner }
-    }
-}
-
 #[derive(Clone, Debug, Deserialize, ToSchema, Serialize, PartialEq)]
 #[serde(deny_unknown_fields)]
 pub struct PrimaryBusinessDetails {
@@ -519,9 +463,8 @@ pub struct PaymentLinkConfig {
 #[serde(deny_unknown_fields)]
 
 pub struct PaymentLinkColorSchema {
-    pub primary_color: Option<String>,
-    pub primary_accent_color: Option<String>,
-    pub secondary_color: Option<String>,
+    pub background_primary_color: Option<String>,
+    pub sdk_theme: Option<String>,
 }
 
 #[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
@@ -949,6 +892,8 @@ pub struct ToggleKVResponse {
 
 #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
 pub struct ToggleKVRequest {
+    #[serde(skip_deserializing)]
+    pub merchant_id: String,
     /// Status of KV for the specific merchant
     #[schema(example = true)]
     pub kv_enabled: bool,
@@ -996,7 +941,7 @@ pub enum PayoutStraightThroughAlgorithm {
     Single(api_enums::PayoutConnectors),
 }
 
-#[derive(Clone, Debug, Deserialize, ToSchema, Default)]
+#[derive(Clone, Debug, Deserialize, ToSchema, Default, Serialize)]
 #[serde(deny_unknown_fields)]
 pub struct BusinessProfileCreate {
     /// A short name to identify the business profile
@@ -1117,7 +1062,7 @@ pub struct BusinessProfileResponse {
     pub applepay_verified_domains: Option<Vec<String>>,
 }
 
-#[derive(Clone, Debug, Deserialize, ToSchema)]
+#[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
 #[serde(deny_unknown_fields)]
 pub struct BusinessProfileUpdate {
     /// A short name to identify the business profile
diff --git a/crates/api_models/src/analytics.rs b/crates/api_models/src/analytics.rs
new file mode 100644
index 000000000000..0358b6b313cf
--- /dev/null
+++ b/crates/api_models/src/analytics.rs
@@ -0,0 +1,152 @@
+use std::collections::HashSet;
+
+use common_utils::events::ApiEventMetric;
+use time::PrimitiveDateTime;
+
+use self::{
+    payments::{PaymentDimensions, PaymentMetrics},
+    refunds::{RefundDimensions, RefundMetrics},
+};
+
+pub mod payments;
+pub mod refunds;
+
+#[derive(Debug, serde::Serialize)]
+pub struct NameDescription {
+    pub name: String,
+    pub desc: String,
+}
+
+#[derive(Debug, serde::Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct GetInfoResponse {
+    pub metrics: Vec<NameDescription>,
+    pub download_dimensions: Option<Vec<NameDescription>>,
+    pub dimensions: Vec<NameDescription>,
+}
+
+impl ApiEventMetric for GetInfoResponse {}
+
+#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash)]
+#[serde(rename_all = "camelCase")]
+pub struct TimeRange {
+    #[serde(with = "common_utils::custom_serde::iso8601")]
+    pub start_time: PrimitiveDateTime,
+    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
+    pub end_time: Option<PrimitiveDateTime>,
+}
+
+#[derive(Clone, Copy, Debug, serde::Deserialize, masking::Serialize)]
+pub struct TimeSeries {
+    pub granularity: Granularity,
+}
+
+#[derive(Clone, Copy, Debug, serde::Deserialize, masking::Serialize)]
+pub enum Granularity {
+    #[serde(rename = "G_ONEMIN")]
+    OneMin,
+    #[serde(rename = "G_FIVEMIN")]
+    FiveMin,
+    #[serde(rename = "G_FIFTEENMIN")]
+    FifteenMin,
+    #[serde(rename = "G_THIRTYMIN")]
+    ThirtyMin,
+    #[serde(rename = "G_ONEHOUR")]
+    OneHour,
+    #[serde(rename = "G_ONEDAY")]
+    OneDay,
+}
+
+#[derive(Clone, Debug, serde::Deserialize, masking::Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct GetPaymentMetricRequest {
+    pub time_series: Option<TimeSeries>,
+    pub time_range: TimeRange,
+    #[serde(default)]
+    pub group_by_names: Vec<PaymentDimensions>,
+    #[serde(default)]
+    pub filters: payments::PaymentFilters,
+    pub metrics: HashSet<PaymentMetrics>,
+    #[serde(default)]
+    pub delta: bool,
+}
+
+impl ApiEventMetric for GetPaymentMetricRequest {}
+
+#[derive(Clone, Debug, serde::Deserialize, masking::Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct GetRefundMetricRequest {
+    pub time_series: Option<TimeSeries>,
+    pub time_range: TimeRange,
+    #[serde(default)]
+    pub group_by_names: Vec<RefundDimensions>,
+    #[serde(default)]
+    pub filters: refunds::RefundFilters,
+    pub metrics: HashSet<RefundMetrics>,
+    #[serde(default)]
+    pub delta: bool,
+}
+
+impl ApiEventMetric for GetRefundMetricRequest {}
+
+#[derive(Debug, serde::Serialize)]
+pub struct AnalyticsMetadata {
+    pub current_time_range: TimeRange,
+}
+
+#[derive(Debug, serde::Deserialize, masking::Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct GetPaymentFiltersRequest {
+    pub time_range: TimeRange,
+    #[serde(default)]
+    pub group_by_names: Vec<PaymentDimensions>,
+}
+
+impl ApiEventMetric for GetPaymentFiltersRequest {}
+
+#[derive(Debug, Default, serde::Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct PaymentFiltersResponse {
+    pub query_data: Vec<FilterValue>,
+}
+
+impl ApiEventMetric for PaymentFiltersResponse {}
+
+#[derive(Debug, serde::Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FilterValue {
+    pub dimension: PaymentDimensions,
+    pub values: Vec<String>,
+}
+
+#[derive(Debug, serde::Deserialize, masking::Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct GetRefundFilterRequest {
+    pub time_range: TimeRange,
+    #[serde(default)]
+    pub group_by_names: Vec<RefundDimensions>,
+}
+
+impl ApiEventMetric for GetRefundFilterRequest {}
+
+#[derive(Debug, Default, serde::Serialize, Eq, PartialEq)]
+#[serde(rename_all = "camelCase")]
+pub struct RefundFiltersResponse {
+    pub query_data: Vec<RefundFilterValue>,
+}
+
+impl ApiEventMetric for RefundFiltersResponse {}
+
+#[derive(Debug, serde::Serialize, Eq, PartialEq)]
+#[serde(rename_all = "camelCase")]
+pub struct RefundFilterValue {
+    pub dimension: RefundDimensions,
+    pub values: Vec<String>,
+}
+
+#[derive(Debug, serde::Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct MetricsResponse<T> {
+    pub query_data: Vec<T>,
+    pub meta_data: [AnalyticsMetadata; 1],
+}
diff --git a/crates/api_models/src/analytics/payments.rs b/crates/api_models/src/analytics/payments.rs
new file mode 100644
index 000000000000..b5e5852d6283
--- /dev/null
+++ b/crates/api_models/src/analytics/payments.rs
@@ -0,0 +1,180 @@
+use std::{
+    collections::hash_map::DefaultHasher,
+    hash::{Hash, Hasher},
+};
+
+use common_enums::enums::{AttemptStatus, AuthenticationType, Currency, PaymentMethod};
+use common_utils::events::ApiEventMetric;
+
+use super::{NameDescription, TimeRange};
+use crate::{analytics::MetricsResponse, enums::Connector};
+
+#[derive(Clone, Debug, Default, serde::Deserialize, masking::Serialize)]
+pub struct PaymentFilters {
+    #[serde(default)]
+    pub currency: Vec<Currency>,
+    #[serde(default)]
+    pub status: Vec<AttemptStatus>,
+    #[serde(default)]
+    pub connector: Vec<Connector>,
+    #[serde(default)]
+    pub auth_type: Vec<AuthenticationType>,
+    #[serde(default)]
+    pub payment_method: Vec<PaymentMethod>,
+}
+
+#[derive(
+    Debug,
+    serde::Serialize,
+    serde::Deserialize,
+    strum::AsRefStr,
+    PartialEq,
+    PartialOrd,
+    Eq,
+    Ord,
+    strum::Display,
+    strum::EnumIter,
+    Clone,
+    Copy,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum PaymentDimensions {
+    // Do not change the order of these enums
+    // Consult the Dashboard FE folks since these also affects the order of metrics on FE
+    Connector,
+    PaymentMethod,
+    Currency,
+    #[strum(serialize = "authentication_type")]
+    #[serde(rename = "authentication_type")]
+    AuthType,
+    #[strum(serialize = "status")]
+    #[serde(rename = "status")]
+    PaymentStatus,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    serde::Serialize,
+    serde::Deserialize,
+    strum::Display,
+    strum::EnumIter,
+    strum::AsRefStr,
+)]
+#[strum(serialize_all = "snake_case")]
+#[serde(rename_all = "snake_case")]
+pub enum PaymentMetrics {
+    PaymentSuccessRate,
+    PaymentCount,
+    PaymentSuccessCount,
+    PaymentProcessedAmount,
+    AvgTicketSize,
+}
+
+pub mod metric_behaviour {
+    pub struct PaymentSuccessRate;
+    pub struct PaymentCount;
+    pub struct PaymentSuccessCount;
+    pub struct PaymentProcessedAmount;
+    pub struct AvgTicketSize;
+}
+
+impl From<PaymentMetrics> for NameDescription {
+    fn from(value: PaymentMetrics) -> Self {
+        Self {
+            name: value.to_string(),
+            desc: String::new(),
+        }
+    }
+}
+
+impl From<PaymentDimensions> for NameDescription {
+    fn from(value: PaymentDimensions) -> Self {
+        Self {
+            name: value.to_string(),
+            desc: String::new(),
+        }
+    }
+}
+
+#[derive(Debug, serde::Serialize, Eq)]
+pub struct PaymentMetricsBucketIdentifier {
+    pub currency: Option<Currency>,
+    pub status: Option<AttemptStatus>,
+    pub connector: Option<String>,
+    #[serde(rename = "authentication_type")]
+    pub auth_type: Option<AuthenticationType>,
+    pub payment_method: Option<String>,
+    #[serde(rename = "time_range")]
+    pub time_bucket: TimeRange,
+    // Coz FE sucks
+    #[serde(rename = "time_bucket")]
+    #[serde(with = "common_utils::custom_serde::iso8601custom")]
+    pub start_time: time::PrimitiveDateTime,
+}
+
+impl PaymentMetricsBucketIdentifier {
+    pub fn new(
+        currency: Option<Currency>,
+        status: Option<AttemptStatus>,
+        connector: Option<String>,
+        auth_type: Option<AuthenticationType>,
+        payment_method: Option<String>,
+        normalized_time_range: TimeRange,
+    ) -> Self {
+        Self {
+            currency,
+            status,
+            connector,
+            auth_type,
+            payment_method,
+            time_bucket: normalized_time_range,
+            start_time: normalized_time_range.start_time,
+        }
+    }
+}
+
+impl Hash for PaymentMetricsBucketIdentifier {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.currency.hash(state);
+        self.status.map(|i| i.to_string()).hash(state);
+        self.connector.hash(state);
+        self.auth_type.map(|i| i.to_string()).hash(state);
+        self.payment_method.hash(state);
+        self.time_bucket.hash(state);
+    }
+}
+
+impl PartialEq for PaymentMetricsBucketIdentifier {
+    fn eq(&self, other: &Self) -> bool {
+        let mut left = DefaultHasher::new();
+        self.hash(&mut left);
+        let mut right = DefaultHasher::new();
+        other.hash(&mut right);
+        left.finish() == right.finish()
+    }
+}
+
+#[derive(Debug, serde::Serialize)]
+pub struct PaymentMetricsBucketValue {
+    pub payment_success_rate: Option<f64>,
+    pub payment_count: Option<u64>,
+    pub payment_success_count: Option<u64>,
+    pub payment_processed_amount: Option<u64>,
+    pub avg_ticket_size: Option<f64>,
+}
+
+#[derive(Debug, serde::Serialize)]
+pub struct MetricsBucketResponse {
+    #[serde(flatten)]
+    pub values: PaymentMetricsBucketValue,
+    #[serde(flatten)]
+    pub dimensions: PaymentMetricsBucketIdentifier,
+}
+
+impl ApiEventMetric for MetricsBucketResponse {}
+impl ApiEventMetric for MetricsResponse<MetricsBucketResponse> {}
diff --git a/crates/api_models/src/analytics/refunds.rs b/crates/api_models/src/analytics/refunds.rs
new file mode 100644
index 000000000000..c5d444338d38
--- /dev/null
+++ b/crates/api_models/src/analytics/refunds.rs
@@ -0,0 +1,183 @@
+use std::{
+    collections::hash_map::DefaultHasher,
+    hash::{Hash, Hasher},
+};
+
+use common_enums::enums::{Currency, RefundStatus};
+use common_utils::events::ApiEventMetric;
+
+use crate::analytics::MetricsResponse;
+
+#[derive(
+    Clone,
+    Copy,
+    Debug,
+    Default,
+    Eq,
+    PartialEq,
+    serde::Serialize,
+    serde::Deserialize,
+    strum::Display,
+    strum::EnumString,
+)]
+// TODO RefundType common_enums need to mapped to storage_model
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum RefundType {
+    InstantRefund,
+    #[default]
+    RegularRefund,
+    RetryRefund,
+}
+
+use super::{NameDescription, TimeRange};
+#[derive(Clone, Debug, Default, serde::Deserialize, masking::Serialize)]
+pub struct RefundFilters {
+    #[serde(default)]
+    pub currency: Vec<Currency>,
+    #[serde(default)]
+    pub refund_status: Vec<RefundStatus>,
+    #[serde(default)]
+    pub connector: Vec<String>,
+    #[serde(default)]
+    pub refund_type: Vec<RefundType>,
+}
+
+#[derive(
+    Debug,
+    serde::Serialize,
+    serde::Deserialize,
+    strum::AsRefStr,
+    PartialEq,
+    PartialOrd,
+    Eq,
+    Ord,
+    strum::Display,
+    strum::EnumIter,
+    Clone,
+    Copy,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum RefundDimensions {
+    Currency,
+    RefundStatus,
+    Connector,
+    RefundType,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    serde::Serialize,
+    serde::Deserialize,
+    strum::Display,
+    strum::EnumIter,
+    strum::AsRefStr,
+)]
+#[strum(serialize_all = "snake_case")]
+#[serde(rename_all = "snake_case")]
+pub enum RefundMetrics {
+    RefundSuccessRate,
+    RefundCount,
+    RefundSuccessCount,
+    RefundProcessedAmount,
+}
+
+pub mod metric_behaviour {
+    pub struct RefundSuccessRate;
+    pub struct RefundCount;
+    pub struct RefundSuccessCount;
+    pub struct RefundProcessedAmount;
+}
+
+impl From<RefundMetrics> for NameDescription {
+    fn from(value: RefundMetrics) -> Self {
+        Self {
+            name: value.to_string(),
+            desc: String::new(),
+        }
+    }
+}
+
+impl From<RefundDimensions> for NameDescription {
+    fn from(value: RefundDimensions) -> Self {
+        Self {
+            name: value.to_string(),
+            desc: String::new(),
+        }
+    }
+}
+
+#[derive(Debug, serde::Serialize, Eq)]
+pub struct RefundMetricsBucketIdentifier {
+    pub currency: Option<Currency>,
+    pub refund_status: Option<RefundStatus>,
+    pub connector: Option<String>,
+    pub refund_type: Option<String>,
+    #[serde(rename = "time_range")]
+    pub time_bucket: TimeRange,
+    #[serde(rename = "time_bucket")]
+    #[serde(with = "common_utils::custom_serde::iso8601custom")]
+    pub start_time: time::PrimitiveDateTime,
+}
+
+impl Hash for RefundMetricsBucketIdentifier {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.currency.hash(state);
+        self.refund_status.map(|i| i.to_string()).hash(state);
+        self.connector.hash(state);
+        self.refund_type.hash(state);
+        self.time_bucket.hash(state);
+    }
+}
+impl PartialEq for RefundMetricsBucketIdentifier {
+    fn eq(&self, other: &Self) -> bool {
+        let mut left = DefaultHasher::new();
+        self.hash(&mut left);
+        let mut right = DefaultHasher::new();
+        other.hash(&mut right);
+        left.finish() == right.finish()
+    }
+}
+
+impl RefundMetricsBucketIdentifier {
+    pub fn new(
+        currency: Option<Currency>,
+        refund_status: Option<RefundStatus>,
+        connector: Option<String>,
+        refund_type: Option<String>,
+        normalized_time_range: TimeRange,
+    ) -> Self {
+        Self {
+            currency,
+            refund_status,
+            connector,
+            refund_type,
+            time_bucket: normalized_time_range,
+            start_time: normalized_time_range.start_time,
+        }
+    }
+}
+
+#[derive(Debug, serde::Serialize)]
+pub struct RefundMetricsBucketValue {
+    pub refund_success_rate: Option<f64>,
+    pub refund_count: Option<u64>,
+    pub refund_success_count: Option<u64>,
+    pub refund_processed_amount: Option<u64>,
+}
+
+#[derive(Debug, serde::Serialize)]
+pub struct RefundMetricsBucketResponse {
+    #[serde(flatten)]
+    pub values: RefundMetricsBucketValue,
+    #[serde(flatten)]
+    pub dimensions: RefundMetricsBucketIdentifier,
+}
+
+impl ApiEventMetric for RefundMetricsBucketResponse {}
+impl ApiEventMetric for MetricsResponse<RefundMetricsBucketResponse> {}
diff --git a/crates/api_models/src/api_keys.rs b/crates/api_models/src/api_keys.rs
index 30f06996939f..805c5616c2a0 100644
--- a/crates/api_models/src/api_keys.rs
+++ b/crates/api_models/src/api_keys.rs
@@ -5,7 +5,7 @@ use time::PrimitiveDateTime;
 use utoipa::ToSchema;
 
 /// The request body for creating an API Key.
-#[derive(Debug, Deserialize, ToSchema)]
+#[derive(Debug, Deserialize, ToSchema, Serialize)]
 #[serde(deny_unknown_fields)]
 pub struct CreateApiKeyRequest {
     /// A unique name for the API Key to help you identify it.
@@ -111,7 +111,7 @@ pub struct RetrieveApiKeyResponse {
 }
 
 /// The request body for updating an API Key.
-#[derive(Debug, Deserialize, ToSchema)]
+#[derive(Debug, Deserialize, ToSchema, Serialize)]
 #[serde(deny_unknown_fields)]
 pub struct UpdateApiKeyRequest {
     /// A unique name for the API Key to help you identify it.
@@ -129,6 +129,12 @@ pub struct UpdateApiKeyRequest {
     /// rotating your keys once every 6 months.
     #[schema(example = "2022-09-10T10:11:12Z")]
     pub expiration: Option<ApiKeyExpiration>,
+
+    #[serde(skip_deserializing)]
+    pub key_id: String,
+
+    #[serde(skip_deserializing)]
+    pub merchant_id: String,
 }
 
 /// The response body for revoking an API Key.
diff --git a/crates/api_models/src/cards_info.rs b/crates/api_models/src/cards_info.rs
index 552f7f54b19e..9eda9c7c57c5 100644
--- a/crates/api_models/src/cards_info.rs
+++ b/crates/api_models/src/cards_info.rs
@@ -8,7 +8,7 @@ pub struct CardsInfoRequestParams {
     pub client_secret: Option<String>,
 }
 
-#[derive(serde::Deserialize, Debug)]
+#[derive(serde::Deserialize, Debug, serde::Serialize)]
 pub struct CardsInfoRequest {
     pub client_secret: Option<String>,
     pub card_iin: String,
diff --git a/crates/api_models/src/disputes.rs b/crates/api_models/src/disputes.rs
index 1b04e7922782..b8955bb8ff55 100644
--- a/crates/api_models/src/disputes.rs
+++ b/crates/api_models/src/disputes.rs
@@ -99,7 +99,7 @@ pub struct DisputeEvidenceBlock {
     pub file_metadata_response: files::FileMetadataResponse,
 }
 
-#[derive(Clone, Debug, Deserialize, ToSchema)]
+#[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
 #[serde(deny_unknown_fields)]
 pub struct DisputeListConstraints {
     /// limit on the number of objects to return
diff --git a/crates/api_models/src/enums.rs b/crates/api_models/src/enums.rs
index a090ee256d0d..eae8be573f58 100644
--- a/crates/api_models/src/enums.rs
+++ b/crates/api_models/src/enums.rs
@@ -75,8 +75,9 @@ pub enum Connector {
     Adyen,
     Airwallex,
     Authorizedotnet,
-    Bitpay,
     Bambora,
+    // Bankofamerica, Added as template code for future usage
+    Bitpay,
     Bluesnap,
     Boku,
     Braintree,
@@ -116,7 +117,7 @@ pub enum Connector {
     Trustpay,
     // Tsys,
     Tsys,
-    //Volt, added as template code for future usage,
+    Volt,
     Wise,
     Worldline,
     Worldpay,
@@ -135,6 +136,7 @@ impl Connector {
                 | (Self::Payu, _)
                 | (Self::Trustpay, PaymentMethod::BankRedirect)
                 | (Self::Iatapay, _)
+                | (Self::Volt, _)
         )
     }
     pub fn supports_file_storage_module(&self) -> bool {
@@ -194,6 +196,7 @@ pub enum RoutableConnectors {
     Adyen,
     Airwallex,
     Authorizedotnet,
+    // Bankofamerica, Added as template code for future usage
     Bitpay,
     Bambora,
     Bluesnap,
@@ -234,7 +237,7 @@ pub enum RoutableConnectors {
     Trustpay,
     // Tsys,
     Tsys,
-    // Volt, added as template code for future usage
+    Volt,
     Wise,
     Worldline,
     Worldpay,
diff --git a/crates/api_models/src/events.rs b/crates/api_models/src/events.rs
new file mode 100644
index 000000000000..ad07340615b4
--- /dev/null
+++ b/crates/api_models/src/events.rs
@@ -0,0 +1,76 @@
+pub mod customer;
+pub mod gsm;
+pub mod payment;
+#[cfg(feature = "payouts")]
+pub mod payouts;
+pub mod refund;
+pub mod routing;
+pub mod user;
+
+use common_utils::{
+    events::{ApiEventMetric, ApiEventsType},
+    impl_misc_api_event_type,
+};
+
+use crate::{
+    admin::*, api_keys::*, cards_info::*, disputes::*, files::*, mandates::*, payment_methods::*,
+    payments::*, verifications::*,
+};
+
+impl ApiEventMetric for TimeRange {}
+
+impl_misc_api_event_type!(
+    PaymentMethodId,
+    PaymentsSessionResponse,
+    PaymentMethodListResponse,
+    PaymentMethodCreate,
+    PaymentLinkInitiateRequest,
+    RetrievePaymentLinkResponse,
+    MandateListConstraints,
+    CreateFileResponse,
+    DisputeResponse,
+    SubmitEvidenceRequest,
+    MerchantConnectorResponse,
+    MerchantConnectorId,
+    MandateResponse,
+    MandateRevokedResponse,
+    RetrievePaymentLinkRequest,
+    MandateId,
+    DisputeListConstraints,
+    RetrieveApiKeyResponse,
+    BusinessProfileResponse,
+    BusinessProfileUpdate,
+    BusinessProfileCreate,
+    RevokeApiKeyResponse,
+    ToggleKVResponse,
+    ToggleKVRequest,
+    MerchantAccountDeleteResponse,
+    MerchantAccountUpdate,
+    CardInfoResponse,
+    CreateApiKeyResponse,
+    CreateApiKeyRequest,
+    MerchantConnectorDeleteResponse,
+    MerchantConnectorUpdate,
+    MerchantConnectorCreate,
+    MerchantId,
+    CardsInfoRequest,
+    MerchantAccountResponse,
+    MerchantAccountListRequest,
+    MerchantAccountCreate,
+    PaymentsSessionRequest,
+    ApplepayMerchantVerificationRequest,
+    ApplepayMerchantResponse,
+    ApplepayVerifiedDomainsResponse,
+    UpdateApiKeyRequest
+);
+
+#[cfg(feature = "stripe")]
+impl_misc_api_event_type!(
+    StripeSetupIntentResponse,
+    StripeRefundResponse,
+    StripePaymentIntentListResponse,
+    StripePaymentIntentResponse,
+    CustomerDeleteResponse,
+    CustomerPaymentMethodListResponse,
+    CreateCustomerResponse
+);
diff --git a/crates/api_models/src/events/customer.rs b/crates/api_models/src/events/customer.rs
new file mode 100644
index 000000000000..29f565042181
--- /dev/null
+++ b/crates/api_models/src/events/customer.rs
@@ -0,0 +1,35 @@
+use common_utils::events::{ApiEventMetric, ApiEventsType};
+
+use crate::customers::{CustomerDeleteResponse, CustomerId, CustomerRequest, CustomerResponse};
+
+impl ApiEventMetric for CustomerDeleteResponse {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Customer {
+            customer_id: self.customer_id.clone(),
+        })
+    }
+}
+
+impl ApiEventMetric for CustomerRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Customer {
+            customer_id: self.customer_id.clone(),
+        })
+    }
+}
+
+impl ApiEventMetric for CustomerResponse {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Customer {
+            customer_id: self.customer_id.clone(),
+        })
+    }
+}
+
+impl ApiEventMetric for CustomerId {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Customer {
+            customer_id: self.customer_id.clone(),
+        })
+    }
+}
diff --git a/crates/api_models/src/events/gsm.rs b/crates/api_models/src/events/gsm.rs
new file mode 100644
index 000000000000..d984ae1ff698
--- /dev/null
+++ b/crates/api_models/src/events/gsm.rs
@@ -0,0 +1,33 @@
+use common_utils::events::{ApiEventMetric, ApiEventsType};
+
+use crate::gsm;
+
+impl ApiEventMetric for gsm::GsmCreateRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Gsm)
+    }
+}
+
+impl ApiEventMetric for gsm::GsmUpdateRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Gsm)
+    }
+}
+
+impl ApiEventMetric for gsm::GsmRetrieveRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Gsm)
+    }
+}
+
+impl ApiEventMetric for gsm::GsmDeleteRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Gsm)
+    }
+}
+
+impl ApiEventMetric for gsm::GsmDeleteResponse {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Gsm)
+    }
+}
diff --git a/crates/api_models/src/events/payment.rs b/crates/api_models/src/events/payment.rs
new file mode 100644
index 000000000000..2f3336fc2777
--- /dev/null
+++ b/crates/api_models/src/events/payment.rs
@@ -0,0 +1,151 @@
+use common_utils::events::{ApiEventMetric, ApiEventsType};
+
+use crate::{
+    payment_methods::{
+        CustomerPaymentMethodsListResponse, PaymentMethodDeleteResponse, PaymentMethodListRequest,
+        PaymentMethodResponse, PaymentMethodUpdate,
+    },
+    payments::{
+        PaymentIdType, PaymentListConstraints, PaymentListFilterConstraints, PaymentListFilters,
+        PaymentListResponse, PaymentListResponseV2, PaymentsApproveRequest, PaymentsCancelRequest,
+        PaymentsCaptureRequest, PaymentsRejectRequest, PaymentsRequest, PaymentsResponse,
+        PaymentsRetrieveRequest, PaymentsStartRequest, RedirectionResponse,
+    },
+};
+impl ApiEventMetric for PaymentsRetrieveRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        match self.resource_id {
+            PaymentIdType::PaymentIntentId(ref id) => Some(ApiEventsType::Payment {
+                payment_id: id.clone(),
+            }),
+            _ => None,
+        }
+    }
+}
+
+impl ApiEventMetric for PaymentsStartRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Payment {
+            payment_id: self.payment_id.clone(),
+        })
+    }
+}
+
+impl ApiEventMetric for PaymentsCaptureRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Payment {
+            payment_id: self.payment_id.to_owned(),
+        })
+    }
+}
+
+impl ApiEventMetric for PaymentsCancelRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Payment {
+            payment_id: self.payment_id.clone(),
+        })
+    }
+}
+
+impl ApiEventMetric for PaymentsApproveRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Payment {
+            payment_id: self.payment_id.clone(),
+        })
+    }
+}
+
+impl ApiEventMetric for PaymentsRejectRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Payment {
+            payment_id: self.payment_id.clone(),
+        })
+    }
+}
+
+impl ApiEventMetric for PaymentsRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        match self.payment_id {
+            Some(PaymentIdType::PaymentIntentId(ref id)) => Some(ApiEventsType::Payment {
+                payment_id: id.clone(),
+            }),
+            _ => None,
+        }
+    }
+}
+
+impl ApiEventMetric for PaymentsResponse {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        self.payment_id
+            .clone()
+            .map(|payment_id| ApiEventsType::Payment { payment_id })
+    }
+}
+
+impl ApiEventMetric for PaymentMethodResponse {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::PaymentMethod {
+            payment_method_id: self.payment_method_id.clone(),
+            payment_method: Some(self.payment_method),
+            payment_method_type: self.payment_method_type,
+        })
+    }
+}
+
+impl ApiEventMetric for PaymentMethodUpdate {}
+
+impl ApiEventMetric for PaymentMethodDeleteResponse {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::PaymentMethod {
+            payment_method_id: self.payment_method_id.clone(),
+            payment_method: None,
+            payment_method_type: None,
+        })
+    }
+}
+
+impl ApiEventMetric for CustomerPaymentMethodsListResponse {}
+
+impl ApiEventMetric for PaymentMethodListRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::PaymentMethodList {
+            payment_id: self
+                .client_secret
+                .as_ref()
+                .and_then(|cs| cs.rsplit_once("_secret_"))
+                .map(|(pid, _)| pid.to_string()),
+        })
+    }
+}
+
+impl ApiEventMetric for PaymentListFilterConstraints {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::ResourceListAPI)
+    }
+}
+
+impl ApiEventMetric for PaymentListFilters {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::ResourceListAPI)
+    }
+}
+
+impl ApiEventMetric for PaymentListConstraints {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::ResourceListAPI)
+    }
+}
+
+impl ApiEventMetric for PaymentListResponse {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::ResourceListAPI)
+    }
+}
+
+impl ApiEventMetric for PaymentListResponseV2 {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::ResourceListAPI)
+    }
+}
+
+impl ApiEventMetric for RedirectionResponse {}
diff --git a/crates/api_models/src/events/payouts.rs b/crates/api_models/src/events/payouts.rs
new file mode 100644
index 000000000000..303709acc476
--- /dev/null
+++ b/crates/api_models/src/events/payouts.rs
@@ -0,0 +1,29 @@
+use common_utils::events::{ApiEventMetric, ApiEventsType};
+
+use crate::payouts::{
+    PayoutActionRequest, PayoutCreateRequest, PayoutCreateResponse, PayoutRetrieveRequest,
+};
+
+impl ApiEventMetric for PayoutRetrieveRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Payout)
+    }
+}
+
+impl ApiEventMetric for PayoutCreateRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Payout)
+    }
+}
+
+impl ApiEventMetric for PayoutCreateResponse {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Payout)
+    }
+}
+
+impl ApiEventMetric for PayoutActionRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Payout)
+    }
+}
diff --git a/crates/api_models/src/events/refund.rs b/crates/api_models/src/events/refund.rs
new file mode 100644
index 000000000000..424a3191db66
--- /dev/null
+++ b/crates/api_models/src/events/refund.rs
@@ -0,0 +1,63 @@
+use common_utils::events::{ApiEventMetric, ApiEventsType};
+
+use crate::refunds::{
+    RefundListMetaData, RefundListRequest, RefundListResponse, RefundRequest, RefundResponse,
+    RefundUpdateRequest, RefundsRetrieveRequest,
+};
+
+impl ApiEventMetric for RefundRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        let payment_id = self.payment_id.clone();
+        self.refund_id
+            .clone()
+            .map(|refund_id| ApiEventsType::Refund {
+                payment_id: Some(payment_id),
+                refund_id,
+            })
+    }
+}
+
+impl ApiEventMetric for RefundResponse {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Refund {
+            payment_id: Some(self.payment_id.clone()),
+            refund_id: self.refund_id.clone(),
+        })
+    }
+}
+
+impl ApiEventMetric for RefundsRetrieveRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Refund {
+            payment_id: None,
+            refund_id: self.refund_id.clone(),
+        })
+    }
+}
+
+impl ApiEventMetric for RefundUpdateRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Refund {
+            payment_id: None,
+            refund_id: self.refund_id.clone(),
+        })
+    }
+}
+
+impl ApiEventMetric for RefundListRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::ResourceListAPI)
+    }
+}
+
+impl ApiEventMetric for RefundListResponse {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::ResourceListAPI)
+    }
+}
+
+impl ApiEventMetric for RefundListMetaData {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::ResourceListAPI)
+    }
+}
diff --git a/crates/api_models/src/events/routing.rs b/crates/api_models/src/events/routing.rs
new file mode 100644
index 000000000000..a09735bc5722
--- /dev/null
+++ b/crates/api_models/src/events/routing.rs
@@ -0,0 +1,70 @@
+use common_utils::events::{ApiEventMetric, ApiEventsType};
+
+use crate::routing::{
+    LinkedRoutingConfigRetrieveResponse, MerchantRoutingAlgorithm, ProfileDefaultRoutingConfig,
+    RoutingAlgorithmId, RoutingConfigRequest, RoutingDictionaryRecord, RoutingKind,
+    RoutingPayloadWrapper,
+};
+#[cfg(feature = "business_profile_routing")]
+use crate::routing::{RoutingRetrieveLinkQuery, RoutingRetrieveQuery};
+
+impl ApiEventMetric for RoutingKind {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Routing)
+    }
+}
+
+impl ApiEventMetric for MerchantRoutingAlgorithm {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Routing)
+    }
+}
+
+impl ApiEventMetric for RoutingAlgorithmId {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Routing)
+    }
+}
+
+impl ApiEventMetric for RoutingDictionaryRecord {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Routing)
+    }
+}
+
+impl ApiEventMetric for LinkedRoutingConfigRetrieveResponse {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Routing)
+    }
+}
+
+impl ApiEventMetric for RoutingPayloadWrapper {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Routing)
+    }
+}
+impl ApiEventMetric for ProfileDefaultRoutingConfig {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Routing)
+    }
+}
+
+#[cfg(feature = "business_profile_routing")]
+impl ApiEventMetric for RoutingRetrieveQuery {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Routing)
+    }
+}
+
+impl ApiEventMetric for RoutingConfigRequest {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Routing)
+    }
+}
+
+#[cfg(feature = "business_profile_routing")]
+impl ApiEventMetric for RoutingRetrieveLinkQuery {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Routing)
+    }
+}
diff --git a/crates/api_models/src/events/user.rs b/crates/api_models/src/events/user.rs
new file mode 100644
index 000000000000..2a896cc38776
--- /dev/null
+++ b/crates/api_models/src/events/user.rs
@@ -0,0 +1,14 @@
+use common_utils::events::{ApiEventMetric, ApiEventsType};
+
+use crate::user::{ConnectAccountRequest, ConnectAccountResponse};
+
+impl ApiEventMetric for ConnectAccountResponse {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::User {
+            merchant_id: self.merchant_id.clone(),
+            user_id: self.user_id.clone(),
+        })
+    }
+}
+
+impl ApiEventMetric for ConnectAccountRequest {}
diff --git a/crates/api_models/src/gsm.rs b/crates/api_models/src/gsm.rs
new file mode 100644
index 000000000000..6bd8fd99dd93
--- /dev/null
+++ b/crates/api_models/src/gsm.rs
@@ -0,0 +1,75 @@
+use crate::enums;
+
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct GsmCreateRequest {
+    pub connector: enums::Connector,
+    pub flow: String,
+    pub sub_flow: String,
+    pub code: String,
+    pub message: String,
+    pub status: String,
+    pub router_error: Option<String>,
+    pub decision: GsmDecision,
+    pub step_up_possible: bool,
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct GsmRetrieveRequest {
+    pub connector: enums::Connector,
+    pub flow: String,
+    pub sub_flow: String,
+    pub code: String,
+    pub message: String,
+}
+
+#[derive(
+    Default,
+    Clone,
+    Copy,
+    Debug,
+    strum::Display,
+    PartialEq,
+    Eq,
+    serde::Serialize,
+    serde::Deserialize,
+    strum::EnumString,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum GsmDecision {
+    Retry,
+    Requeue,
+    #[default]
+    DoDefault,
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct GsmUpdateRequest {
+    pub connector: String,
+    pub flow: String,
+    pub sub_flow: String,
+    pub code: String,
+    pub message: String,
+    pub status: Option<String>,
+    pub router_error: Option<String>,
+    pub decision: Option<GsmDecision>,
+    pub step_up_possible: Option<bool>,
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct GsmDeleteRequest {
+    pub connector: String,
+    pub flow: String,
+    pub sub_flow: String,
+    pub code: String,
+    pub message: String,
+}
+
+#[derive(Debug, serde::Serialize)]
+pub struct GsmDeleteResponse {
+    pub gsm_rule_delete: bool,
+    pub connector: String,
+    pub flow: String,
+    pub sub_flow: String,
+    pub code: String,
+}
diff --git a/crates/api_models/src/lib.rs b/crates/api_models/src/lib.rs
index 29ad9be051b6..bcc3913ea824 100644
--- a/crates/api_models/src/lib.rs
+++ b/crates/api_models/src/lib.rs
@@ -1,5 +1,6 @@
 #![forbid(unsafe_code)]
 pub mod admin;
+pub mod analytics;
 pub mod api_keys;
 pub mod bank_accounts;
 pub mod cards_info;
@@ -9,12 +10,17 @@ pub mod enums;
 pub mod ephemeral_key;
 #[cfg(feature = "errors")]
 pub mod errors;
+pub mod events;
 pub mod files;
+pub mod gsm;
 pub mod mandates;
+pub mod organization;
 pub mod payment_methods;
 pub mod payments;
 #[cfg(feature = "payouts")]
 pub mod payouts;
 pub mod refunds;
+pub mod routing;
+pub mod user;
 pub mod verifications;
 pub mod webhooks;
diff --git a/crates/api_models/src/mandates.rs b/crates/api_models/src/mandates.rs
index ca0037db85be..035f7adec9f7 100644
--- a/crates/api_models/src/mandates.rs
+++ b/crates/api_models/src/mandates.rs
@@ -62,7 +62,7 @@ pub struct MandateCardDetails {
     pub card_fingerprint: Option<Secret<String>>,
 }
 
-#[derive(Clone, Debug, Deserialize, ToSchema)]
+#[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
 #[serde(deny_unknown_fields)]
 pub struct MandateListConstraints {
     /// limit on the number of objects to return
diff --git a/crates/api_models/src/organization.rs b/crates/api_models/src/organization.rs
new file mode 100644
index 000000000000..db4ae21a0dfb
--- /dev/null
+++ b/crates/api_models/src/organization.rs
@@ -0,0 +1,13 @@
+pub struct OrganizationNew {
+    pub org_id: String,
+    pub org_name: Option<String>,
+}
+
+impl OrganizationNew {
+    pub fn new(org_name: Option<String>) -> Self {
+        Self {
+            org_id: common_utils::generate_id_with_default_len("org"),
+            org_name,
+        }
+    }
+}
diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs
index 4656f6362cd1..755acbf7f425 100644
--- a/crates/api_models/src/payment_methods.rs
+++ b/crates/api_models/src/payment_methods.rs
@@ -6,14 +6,15 @@ use common_utils::{
     types::Percentage,
 };
 use serde::de;
-use serde_with::serde_as;
 use utoipa::ToSchema;
 
 #[cfg(feature = "payouts")]
 use crate::payouts;
 use crate::{
-    admin, enums as api_enums,
-    payments::{self, BankCodeResponse},
+    admin,
+    customers::CustomerId,
+    enums as api_enums,
+    payments::{self, BankCodeResponse, RequestSurchargeDetails},
 };
 
 #[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
@@ -167,6 +168,8 @@ pub struct CardDetailsPaymentMethod {
 pub struct PaymentMethodDataBankCreds {
     pub mask: String,
     pub hash: String,
+    pub account_type: Option<String>,
+    pub account_name: Option<String>,
     pub payment_method_type: api_enums::PaymentMethodType,
     pub connector_details: Vec<BankAccountConnectorDetails>,
 }
@@ -338,11 +341,98 @@ pub struct SurchargeDetailsResponse {
     pub final_amount: i64,
 }
 
-#[serde_as]
-#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
+impl SurchargeDetailsResponse {
+    pub fn is_request_surcharge_matching(
+        &self,
+        request_surcharge_details: RequestSurchargeDetails,
+    ) -> bool {
+        request_surcharge_details.surcharge_amount == self.surcharge_amount
+            && request_surcharge_details.tax_amount.unwrap_or(0) == self.tax_on_surcharge_amount
+    }
+}
+
+#[derive(Clone, Debug)]
 pub struct SurchargeMetadata {
-    #[serde_as(as = "HashMap<_, _>")]
-    pub surcharge_results: HashMap<String, SurchargeDetailsResponse>,
+    surcharge_results: HashMap<
+        (
+            common_enums::PaymentMethod,
+            common_enums::PaymentMethodType,
+            Option<common_enums::CardNetwork>,
+        ),
+        SurchargeDetailsResponse,
+    >,
+    pub payment_attempt_id: String,
+}
+
+impl SurchargeMetadata {
+    pub fn new(payment_attempt_id: String) -> Self {
+        Self {
+            surcharge_results: HashMap::new(),
+            payment_attempt_id,
+        }
+    }
+    pub fn is_empty_result(&self) -> bool {
+        self.surcharge_results.is_empty()
+    }
+    pub fn get_surcharge_results_size(&self) -> usize {
+        self.surcharge_results.len()
+    }
+    pub fn insert_surcharge_details(
+        &mut self,
+        payment_method: &common_enums::PaymentMethod,
+        payment_method_type: &common_enums::PaymentMethodType,
+        card_network: Option<&common_enums::CardNetwork>,
+        surcharge_details: SurchargeDetailsResponse,
+    ) {
+        let key = (
+            payment_method.to_owned(),
+            payment_method_type.to_owned(),
+            card_network.cloned(),
+        );
+        self.surcharge_results.insert(key, surcharge_details);
+    }
+    pub fn get_surcharge_details(
+        &self,
+        payment_method: &common_enums::PaymentMethod,
+        payment_method_type: &common_enums::PaymentMethodType,
+        card_network: Option<&common_enums::CardNetwork>,
+    ) -> Option<&SurchargeDetailsResponse> {
+        let key = &(
+            payment_method.to_owned(),
+            payment_method_type.to_owned(),
+            card_network.cloned(),
+        );
+        self.surcharge_results.get(key)
+    }
+    pub fn get_surcharge_metadata_redis_key(payment_attempt_id: &str) -> String {
+        format!("surcharge_metadata_{}", payment_attempt_id)
+    }
+    pub fn get_individual_surcharge_key_value_pairs(
+        &self,
+    ) -> Vec<(String, SurchargeDetailsResponse)> {
+        self.surcharge_results
+            .iter()
+            .map(|((pm, pmt, card_network), surcharge_details)| {
+                let key =
+                    Self::get_surcharge_details_redis_hashset_key(pm, pmt, card_network.as_ref());
+                (key, surcharge_details.to_owned())
+            })
+            .collect()
+    }
+    pub fn get_surcharge_details_redis_hashset_key(
+        payment_method: &common_enums::PaymentMethod,
+        payment_method_type: &common_enums::PaymentMethodType,
+        card_network: Option<&common_enums::CardNetwork>,
+    ) -> String {
+        if let Some(card_network) = card_network {
+            format!(
+                "{}_{}_{}",
+                payment_method, payment_method_type, card_network
+            )
+        } else {
+            format!("{}_{}", payment_method, payment_method_type)
+        }
+    }
 }
 
 #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
@@ -457,6 +547,8 @@ pub struct RequestPaymentMethodTypes {
 #[derive(Debug, Clone, serde::Serialize, Default, ToSchema)]
 #[serde(deny_unknown_fields)]
 pub struct PaymentMethodListRequest {
+    #[serde(skip_deserializing)]
+    pub customer_id: Option<CustomerId>,
     /// This is a 15 minute expiry token which shall be used from the client to authenticate and perform sessions from the SDK
     #[schema(max_length = 30, min_length = 30, example = "secret_k2uj3he2893ein2d")]
     pub client_secret: Option<String>,
@@ -754,6 +846,13 @@ pub struct DeleteTokenizeByTokenRequest {
     pub service_name: String,
 }
 
+#[derive(Debug, serde::Serialize)] // Blocked: Yet to be implemented by `basilisk`
+pub struct DeleteTokenizeByDateRequest {
+    pub buffer_minutes: i32,
+    pub service_name: String,
+    pub max_rows: i32,
+}
+
 #[derive(Debug, serde::Deserialize)]
 pub struct GetTokenizePayloadResponse {
     pub lookup_key: String,
diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs
index 31a0cd06b50c..d924fb2e4f62 100644
--- a/crates/api_models/src/payments.rs
+++ b/crates/api_models/src/payments.rs
@@ -16,6 +16,7 @@ use crate::{
     admin, disputes,
     enums::{self as api_enums},
     ephemeral_key::EphemeralKeyCreateResponse,
+    payment_methods::{Surcharge, SurchargeDetailsResponse},
     refunds,
 };
 
@@ -319,6 +320,23 @@ pub struct RequestSurchargeDetails {
     pub tax_amount: Option<i64>,
 }
 
+impl RequestSurchargeDetails {
+    pub fn is_surcharge_zero(&self) -> bool {
+        self.surcharge_amount == 0 && self.tax_amount.unwrap_or(0) == 0
+    }
+    pub fn get_surcharge_details_object(&self, original_amount: i64) -> SurchargeDetailsResponse {
+        let surcharge_amount = self.surcharge_amount;
+        let tax_on_surcharge_amount = self.tax_amount.unwrap_or(0);
+        SurchargeDetailsResponse {
+            surcharge: Surcharge::Fixed(self.surcharge_amount),
+            tax_on_surcharge: None,
+            surcharge_amount,
+            tax_on_surcharge_amount,
+            final_amount: original_amount + surcharge_amount + tax_on_surcharge_amount,
+        }
+    }
+}
+
 #[derive(Default, Debug, Clone, Copy)]
 pub struct HeaderPayload {
     pub payment_confirm_source: Option<api_enums::PaymentSource>,
@@ -811,6 +829,36 @@ pub enum PaymentMethodData {
     GiftCard(Box<GiftCardData>),
 }
 
+impl PaymentMethodData {
+    pub fn get_payment_method_type_if_session_token_type(
+        &self,
+    ) -> Option<api_enums::PaymentMethodType> {
+        match self {
+            Self::Wallet(wallet) => match wallet {
+                WalletData::ApplePay(_) => Some(api_enums::PaymentMethodType::ApplePay),
+                WalletData::GooglePay(_) => Some(api_enums::PaymentMethodType::GooglePay),
+                WalletData::PaypalSdk(_) => Some(api_enums::PaymentMethodType::Paypal),
+                _ => None,
+            },
+            Self::PayLater(pay_later) => match pay_later {
+                PayLaterData::KlarnaSdk { .. } => Some(api_enums::PaymentMethodType::Klarna),
+                _ => None,
+            },
+            Self::Card(_)
+            | Self::CardRedirect(_)
+            | Self::BankRedirect(_)
+            | Self::BankDebit(_)
+            | Self::BankTransfer(_)
+            | Self::Crypto(_)
+            | Self::MandatePayment
+            | Self::Reward
+            | Self::Upi(_)
+            | Self::Voucher(_)
+            | Self::GiftCard(_) => None,
+        }
+    }
+}
+
 pub trait GetPaymentMethodType {
     fn get_payment_method_type(&self) -> api_enums::PaymentMethodType;
 }
@@ -2108,9 +2156,12 @@ pub struct PaymentsResponse {
 
     /// Denotes the action(approve or reject) taken by merchant in case of manual review. Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment
     pub merchant_decision: Option<String>,
+
+    /// Identifier of the connector ( merchant connector account ) which was chosen to make the payment
+    pub merchant_connector_id: Option<String>,
 }
 
-#[derive(Clone, Debug, serde::Deserialize, ToSchema)]
+#[derive(Clone, Debug, serde::Deserialize, ToSchema, serde::Serialize)]
 #[serde(deny_unknown_fields)]
 pub struct PaymentListConstraints {
     /// The identifier for customer
@@ -2186,7 +2237,7 @@ pub struct PaymentListResponseV2 {
     pub data: Vec<PaymentsResponse>,
 }
 
-#[derive(Clone, Debug, serde::Deserialize)]
+#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
 pub struct PaymentListFilterConstraints {
     /// The identifier for payment
     pub payment_id: Option<String>,
@@ -2231,7 +2282,9 @@ pub struct PaymentListFilters {
     pub authentication_type: Vec<enums::AuthenticationType>,
 }
 
-#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash)]
+#[derive(
+    Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash, ToSchema,
+)]
 pub struct TimeRange {
     /// The start time to filter payments list or to get list of filters. To get list of filters start time is needed to be passed
     #[serde(with = "common_utils::custom_serde::iso8601")]
@@ -3097,9 +3150,11 @@ pub struct PaymentLinkObject {
     #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
     pub link_expiry: Option<PrimitiveDateTime>,
     pub merchant_custom_domain_name: Option<String>,
+    /// Custom merchant name for payment link
+    pub custom_merchant_name: Option<String>,
 }
 
-#[derive(Default, Debug, serde::Deserialize, Clone, ToSchema)]
+#[derive(Default, Debug, serde::Deserialize, Clone, ToSchema, serde::Serialize)]
 pub struct RetrievePaymentLinkRequest {
     pub client_secret: Option<String>,
 }
@@ -3127,7 +3182,7 @@ pub struct RetrievePaymentLinkResponse {
     pub link_expiry: Option<PrimitiveDateTime>,
 }
 
-#[derive(Clone, Debug, serde::Deserialize, ToSchema)]
+#[derive(Clone, Debug, serde::Deserialize, ToSchema, serde::Serialize)]
 pub struct PaymentLinkInitiateRequest {
     pub merchant_id: String,
     pub payment_id: String,
@@ -3140,11 +3195,12 @@ pub struct PaymentLinkDetails {
     pub pub_key: String,
     pub client_secret: String,
     pub payment_id: String,
-    #[serde(with = "common_utils::custom_serde::iso8601")]
-    pub expiry: PrimitiveDateTime,
+    #[serde(with = "common_utils::custom_serde::iso8601::option")]
+    pub expiry: Option<PrimitiveDateTime>,
     pub merchant_logo: String,
     pub return_url: String,
-    pub merchant_name: crypto::OptionalEncryptableName,
-    pub order_details: Vec<pii::SecretSerdeValue>,
+    pub merchant_name: String,
+    pub order_details: Option<Vec<OrderDetailsWithAmount>>,
     pub max_items_visible_after_collapse: i8,
+    pub sdk_theme: Option<String>,
 }
diff --git a/crates/api_models/src/refunds.rs b/crates/api_models/src/refunds.rs
index 489c5dd1c436..6fe8be8b5291 100644
--- a/crates/api_models/src/refunds.rs
+++ b/crates/api_models/src/refunds.rs
@@ -3,9 +3,10 @@ use serde::{Deserialize, Serialize};
 use time::PrimitiveDateTime;
 use utoipa::ToSchema;
 
+use super::payments::TimeRange;
 use crate::{admin, enums};
 
-#[derive(Default, Debug, ToSchema, Clone, Deserialize)]
+#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)]
 #[serde(deny_unknown_fields)]
 pub struct RefundRequest {
     /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refund initiated against the same payment. If the identifiers is not defined by the merchant, this filed shall be auto generated and provide in the API response. It is recommended to generate uuid(v4) as the refund_id.
@@ -54,7 +55,7 @@ pub struct RefundsRetrieveBody {
     pub force_sync: Option<bool>,
 }
 
-#[derive(Default, Debug, ToSchema, Clone, Deserialize)]
+#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)]
 pub struct RefundsRetrieveRequest {
     /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refund initiated against the same payment. If the identifiers is not defined by the merchant, this filed shall be auto generated and provide in the API response. It is recommended to generate uuid(v4) as the refund_id.
     #[schema(
@@ -72,9 +73,11 @@ pub struct RefundsRetrieveRequest {
     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,
 }
 
-#[derive(Default, Debug, ToSchema, Clone, Deserialize)]
+#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)]
 #[serde(deny_unknown_fields)]
 pub struct RefundUpdateRequest {
+    #[serde(skip)]
+    pub refund_id: String,
     /// An arbitrary string attached to the object. Often useful for displaying to users and your customer support executive
     #[schema(max_length = 255, example = "Customer returned the product")]
     pub reason: Option<String>,
@@ -124,6 +127,7 @@ pub struct RefundResponse {
     /// The connector used for the refund and the corresponding payment
     #[schema(example = "stripe")]
     pub connector: String,
+    pub profile_id: Option<String>,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)]
@@ -151,16 +155,6 @@ pub struct RefundListRequest {
     pub refund_status: Option<Vec<enums::RefundStatus>>,
 }
 
-#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash, ToSchema)]
-pub struct TimeRange {
-    /// The start time to filter refunds list or to get list of filters. To get list of filters start time is needed to be passed
-    #[serde(with = "common_utils::custom_serde::iso8601")]
-    pub start_time: PrimitiveDateTime,
-    /// The end time to filter refunds list or to get list of filters. If not passed the default time is now
-    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
-    pub end_time: Option<PrimitiveDateTime>,
-}
-
 #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)]
 pub struct RefundListResponse {
     /// The number of refunds included in the list
diff --git a/crates/api_models/src/routing.rs b/crates/api_models/src/routing.rs
new file mode 100644
index 000000000000..363df5389a79
--- /dev/null
+++ b/crates/api_models/src/routing.rs
@@ -0,0 +1,612 @@
+use std::fmt::Debug;
+
+use common_utils::errors::ParsingError;
+use error_stack::IntoReport;
+use euclid::{
+    dssa::types::EuclidAnalysable,
+    enums as euclid_enums,
+    frontend::{
+        ast,
+        dir::{DirKeyKind, EuclidDirFilter},
+    },
+};
+use serde::{Deserialize, Serialize};
+
+use crate::enums::{self, RoutableConnectors};
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(tag = "type", content = "data", rename_all = "snake_case")]
+pub enum ConnectorSelection {
+    Priority(Vec<RoutableConnectorChoice>),
+    VolumeSplit(Vec<ConnectorVolumeSplit>),
+}
+
+impl ConnectorSelection {
+    pub fn get_connector_list(&self) -> Vec<RoutableConnectorChoice> {
+        match self {
+            Self::Priority(list) => list.clone(),
+            Self::VolumeSplit(splits) => {
+                splits.iter().map(|split| split.connector.clone()).collect()
+            }
+        }
+    }
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct RoutingConfigRequest {
+    pub name: Option<String>,
+    pub description: Option<String>,
+    pub algorithm: Option<RoutingAlgorithm>,
+    pub profile_id: Option<String>,
+}
+
+#[derive(Debug, serde::Serialize)]
+pub struct ProfileDefaultRoutingConfig {
+    pub profile_id: String,
+    pub connectors: Vec<RoutableConnectorChoice>,
+}
+
+#[cfg(feature = "business_profile_routing")]
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct RoutingRetrieveQuery {
+    pub limit: Option<u16>,
+    pub offset: Option<u8>,
+
+    pub profile_id: Option<String>,
+}
+
+#[cfg(feature = "business_profile_routing")]
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct RoutingRetrieveLinkQuery {
+    pub profile_id: Option<String>,
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct RoutingRetrieveResponse {
+    pub algorithm: Option<MerchantRoutingAlgorithm>,
+}
+
+#[derive(Debug, serde::Serialize)]
+#[serde(untagged)]
+pub enum LinkedRoutingConfigRetrieveResponse {
+    MerchantAccountBased(RoutingRetrieveResponse),
+    ProfileBased(Vec<RoutingDictionaryRecord>),
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct MerchantRoutingAlgorithm {
+    pub id: String,
+    #[cfg(feature = "business_profile_routing")]
+    pub profile_id: String,
+    pub name: String,
+    pub description: String,
+    pub algorithm: RoutingAlgorithm,
+    pub created_at: i64,
+    pub modified_at: i64,
+}
+
+impl EuclidDirFilter for ConnectorSelection {
+    const ALLOWED: &'static [DirKeyKind] = &[
+        DirKeyKind::PaymentMethod,
+        DirKeyKind::CardBin,
+        DirKeyKind::CardType,
+        DirKeyKind::CardNetwork,
+        DirKeyKind::PayLaterType,
+        DirKeyKind::WalletType,
+        DirKeyKind::UpiType,
+        DirKeyKind::BankRedirectType,
+        DirKeyKind::BankDebitType,
+        DirKeyKind::CryptoType,
+        DirKeyKind::MetaData,
+        DirKeyKind::PaymentAmount,
+        DirKeyKind::PaymentCurrency,
+        DirKeyKind::AuthenticationType,
+        DirKeyKind::MandateAcceptanceType,
+        DirKeyKind::MandateType,
+        DirKeyKind::PaymentType,
+        DirKeyKind::SetupFutureUsage,
+        DirKeyKind::CaptureMethod,
+        DirKeyKind::BillingCountry,
+        DirKeyKind::BusinessCountry,
+        DirKeyKind::BusinessLabel,
+        DirKeyKind::MetaData,
+        DirKeyKind::RewardType,
+        DirKeyKind::VoucherType,
+        DirKeyKind::CardRedirectType,
+        DirKeyKind::BankTransferType,
+    ];
+}
+
+impl EuclidAnalysable for ConnectorSelection {
+    fn get_dir_value_for_analysis(
+        &self,
+        rule_name: String,
+    ) -> Vec<(euclid::frontend::dir::DirValue, euclid::types::Metadata)> {
+        self.get_connector_list()
+            .into_iter()
+            .map(|connector_choice| {
+                let connector_name = connector_choice.connector.to_string();
+                #[cfg(not(feature = "connector_choice_mca_id"))]
+                let sub_label = connector_choice.sub_label.clone();
+                #[cfg(feature = "connector_choice_mca_id")]
+                let mca_id = connector_choice.merchant_connector_id.clone();
+
+                (
+                    euclid::frontend::dir::DirValue::Connector(Box::new(connector_choice.into())),
+                    std::collections::HashMap::from_iter([(
+                        "CONNECTOR_SELECTION".to_string(),
+                        #[cfg(feature = "connector_choice_mca_id")]
+                        serde_json::json!({
+                            "rule_name": rule_name,
+                            "connector_name": connector_name,
+                            "mca_id": mca_id,
+                        }),
+                        #[cfg(not(feature = "connector_choice_mca_id"))]
+                        serde_json ::json!({
+                            "rule_name": rule_name,
+                            "connector_name": connector_name,
+                            "sub_label": sub_label,
+                        }),
+                    )]),
+                )
+            })
+            .collect()
+    }
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct ConnectorVolumeSplit {
+    pub connector: RoutableConnectorChoice,
+    pub split: u8,
+}
+
+#[cfg(feature = "connector_choice_bcompat")]
+#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
+pub enum RoutableChoiceKind {
+    OnlyConnector,
+    FullStruct,
+}
+
+#[cfg(feature = "connector_choice_bcompat")]
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+#[serde(untagged)]
+pub enum RoutableChoiceSerde {
+    OnlyConnector(Box<RoutableConnectors>),
+    FullStruct {
+        connector: RoutableConnectors,
+        #[cfg(feature = "connector_choice_mca_id")]
+        merchant_connector_id: Option<String>,
+        #[cfg(not(feature = "connector_choice_mca_id"))]
+        sub_label: Option<String>,
+    },
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+#[cfg_attr(
+    feature = "connector_choice_bcompat",
+    serde(from = "RoutableChoiceSerde"),
+    serde(into = "RoutableChoiceSerde")
+)]
+#[cfg_attr(not(feature = "connector_choice_bcompat"), derive(PartialEq, Eq))]
+pub struct RoutableConnectorChoice {
+    #[cfg(feature = "connector_choice_bcompat")]
+    pub choice_kind: RoutableChoiceKind,
+    pub connector: RoutableConnectors,
+    #[cfg(feature = "connector_choice_mca_id")]
+    pub merchant_connector_id: Option<String>,
+    #[cfg(not(feature = "connector_choice_mca_id"))]
+    pub sub_label: Option<String>,
+}
+
+impl ToString for RoutableConnectorChoice {
+    fn to_string(&self) -> String {
+        #[cfg(feature = "connector_choice_mca_id")]
+        let base = self.connector.to_string();
+
+        #[cfg(not(feature = "connector_choice_mca_id"))]
+        let base = {
+            let mut sub_base = self.connector.to_string();
+            if let Some(ref label) = self.sub_label {
+                sub_base.push('_');
+                sub_base.push_str(label);
+            }
+
+            sub_base
+        };
+
+        base
+    }
+}
+
+#[cfg(feature = "connector_choice_bcompat")]
+impl PartialEq for RoutableConnectorChoice {
+    fn eq(&self, other: &Self) -> bool {
+        #[cfg(not(feature = "connector_choice_mca_id"))]
+        {
+            self.connector.eq(&other.connector) && self.sub_label.eq(&other.sub_label)
+        }
+
+        #[cfg(feature = "connector_choice_mca_id")]
+        {
+            self.connector.eq(&other.connector)
+                && self.merchant_connector_id.eq(&other.merchant_connector_id)
+        }
+    }
+}
+
+#[cfg(feature = "connector_choice_bcompat")]
+impl Eq for RoutableConnectorChoice {}
+
+#[cfg(feature = "connector_choice_bcompat")]
+impl From<RoutableChoiceSerde> for RoutableConnectorChoice {
+    fn from(value: RoutableChoiceSerde) -> Self {
+        match value {
+            RoutableChoiceSerde::OnlyConnector(connector) => Self {
+                choice_kind: RoutableChoiceKind::OnlyConnector,
+                connector: *connector,
+                #[cfg(feature = "connector_choice_mca_id")]
+                merchant_connector_id: None,
+                #[cfg(not(feature = "connector_choice_mca_id"))]
+                sub_label: None,
+            },
+
+            RoutableChoiceSerde::FullStruct {
+                connector,
+                #[cfg(feature = "connector_choice_mca_id")]
+                merchant_connector_id,
+                #[cfg(not(feature = "connector_choice_mca_id"))]
+                sub_label,
+            } => Self {
+                choice_kind: RoutableChoiceKind::FullStruct,
+                connector,
+                #[cfg(feature = "connector_choice_mca_id")]
+                merchant_connector_id,
+                #[cfg(not(feature = "connector_choice_mca_id"))]
+                sub_label,
+            },
+        }
+    }
+}
+
+#[cfg(feature = "connector_choice_bcompat")]
+impl From<RoutableConnectorChoice> for RoutableChoiceSerde {
+    fn from(value: RoutableConnectorChoice) -> Self {
+        match value.choice_kind {
+            RoutableChoiceKind::OnlyConnector => Self::OnlyConnector(Box::new(value.connector)),
+            RoutableChoiceKind::FullStruct => Self::FullStruct {
+                connector: value.connector,
+                #[cfg(feature = "connector_choice_mca_id")]
+                merchant_connector_id: value.merchant_connector_id,
+                #[cfg(not(feature = "connector_choice_mca_id"))]
+                sub_label: value.sub_label,
+            },
+        }
+    }
+}
+
+impl From<RoutableConnectorChoice> for ast::ConnectorChoice {
+    fn from(value: RoutableConnectorChoice) -> Self {
+        Self {
+            connector: match value.connector {
+                #[cfg(feature = "dummy_connector")]
+                RoutableConnectors::DummyConnector1 => euclid_enums::Connector::DummyConnector1,
+                #[cfg(feature = "dummy_connector")]
+                RoutableConnectors::DummyConnector2 => euclid_enums::Connector::DummyConnector2,
+                #[cfg(feature = "dummy_connector")]
+                RoutableConnectors::DummyConnector3 => euclid_enums::Connector::DummyConnector3,
+                #[cfg(feature = "dummy_connector")]
+                RoutableConnectors::DummyConnector4 => euclid_enums::Connector::DummyConnector4,
+                #[cfg(feature = "dummy_connector")]
+                RoutableConnectors::DummyConnector5 => euclid_enums::Connector::DummyConnector5,
+                #[cfg(feature = "dummy_connector")]
+                RoutableConnectors::DummyConnector6 => euclid_enums::Connector::DummyConnector6,
+                #[cfg(feature = "dummy_connector")]
+                RoutableConnectors::DummyConnector7 => euclid_enums::Connector::DummyConnector7,
+                RoutableConnectors::Aci => euclid_enums::Connector::Aci,
+                RoutableConnectors::Adyen => euclid_enums::Connector::Adyen,
+                RoutableConnectors::Airwallex => euclid_enums::Connector::Airwallex,
+                RoutableConnectors::Authorizedotnet => euclid_enums::Connector::Authorizedotnet,
+                RoutableConnectors::Bitpay => euclid_enums::Connector::Bitpay,
+                RoutableConnectors::Bambora => euclid_enums::Connector::Bambora,
+                RoutableConnectors::Bluesnap => euclid_enums::Connector::Bluesnap,
+                RoutableConnectors::Boku => euclid_enums::Connector::Boku,
+                RoutableConnectors::Braintree => euclid_enums::Connector::Braintree,
+                RoutableConnectors::Cashtocode => euclid_enums::Connector::Cashtocode,
+                RoutableConnectors::Checkout => euclid_enums::Connector::Checkout,
+                RoutableConnectors::Coinbase => euclid_enums::Connector::Coinbase,
+                RoutableConnectors::Cryptopay => euclid_enums::Connector::Cryptopay,
+                RoutableConnectors::Cybersource => euclid_enums::Connector::Cybersource,
+                RoutableConnectors::Dlocal => euclid_enums::Connector::Dlocal,
+                RoutableConnectors::Fiserv => euclid_enums::Connector::Fiserv,
+                RoutableConnectors::Forte => euclid_enums::Connector::Forte,
+                RoutableConnectors::Globalpay => euclid_enums::Connector::Globalpay,
+                RoutableConnectors::Globepay => euclid_enums::Connector::Globepay,
+                RoutableConnectors::Gocardless => euclid_enums::Connector::Gocardless,
+                RoutableConnectors::Helcim => euclid_enums::Connector::Helcim,
+                RoutableConnectors::Iatapay => euclid_enums::Connector::Iatapay,
+                RoutableConnectors::Klarna => euclid_enums::Connector::Klarna,
+                RoutableConnectors::Mollie => euclid_enums::Connector::Mollie,
+                RoutableConnectors::Multisafepay => euclid_enums::Connector::Multisafepay,
+                RoutableConnectors::Nexinets => euclid_enums::Connector::Nexinets,
+                RoutableConnectors::Nmi => euclid_enums::Connector::Nmi,
+                RoutableConnectors::Noon => euclid_enums::Connector::Noon,
+                RoutableConnectors::Nuvei => euclid_enums::Connector::Nuvei,
+                RoutableConnectors::Opennode => euclid_enums::Connector::Opennode,
+                RoutableConnectors::Payme => euclid_enums::Connector::Payme,
+                RoutableConnectors::Paypal => euclid_enums::Connector::Paypal,
+                RoutableConnectors::Payu => euclid_enums::Connector::Payu,
+                RoutableConnectors::Powertranz => euclid_enums::Connector::Powertranz,
+                RoutableConnectors::Rapyd => euclid_enums::Connector::Rapyd,
+                RoutableConnectors::Shift4 => euclid_enums::Connector::Shift4,
+                RoutableConnectors::Square => euclid_enums::Connector::Square,
+                RoutableConnectors::Stax => euclid_enums::Connector::Stax,
+                RoutableConnectors::Stripe => euclid_enums::Connector::Stripe,
+                RoutableConnectors::Trustpay => euclid_enums::Connector::Trustpay,
+                RoutableConnectors::Tsys => euclid_enums::Connector::Tsys,
+                RoutableConnectors::Volt => euclid_enums::Connector::Volt,
+                RoutableConnectors::Wise => euclid_enums::Connector::Wise,
+                RoutableConnectors::Worldline => euclid_enums::Connector::Worldline,
+                RoutableConnectors::Worldpay => euclid_enums::Connector::Worldpay,
+                RoutableConnectors::Zen => euclid_enums::Connector::Zen,
+            },
+
+            #[cfg(not(feature = "connector_choice_mca_id"))]
+            sub_label: value.sub_label,
+        }
+    }
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct DetailedConnectorChoice {
+    pub connector: RoutableConnectors,
+    pub business_label: Option<String>,
+    pub business_country: Option<enums::CountryAlpha2>,
+    pub business_sub_label: Option<String>,
+}
+
+impl DetailedConnectorChoice {
+    pub fn get_connector_label(&self) -> Option<String> {
+        self.business_country
+            .as_ref()
+            .zip(self.business_label.as_ref())
+            .map(|(business_country, business_label)| {
+                let mut base_label = format!(
+                    "{}_{:?}_{}",
+                    self.connector, business_country, business_label
+                );
+
+                if let Some(ref sub_label) = self.business_sub_label {
+                    base_label.push('_');
+                    base_label.push_str(sub_label);
+                }
+
+                base_label
+            })
+    }
+}
+
+#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize, strum::Display)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum RoutingAlgorithmKind {
+    Single,
+    Priority,
+    VolumeSplit,
+    Advanced,
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+
+pub struct RoutingPayloadWrapper {
+    pub updated_config: Vec<RoutableConnectorChoice>,
+    pub profile_id: String,
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+#[serde(
+    tag = "type",
+    content = "data",
+    rename_all = "snake_case",
+    try_from = "RoutingAlgorithmSerde"
+)]
+pub enum RoutingAlgorithm {
+    Single(Box<RoutableConnectorChoice>),
+    Priority(Vec<RoutableConnectorChoice>),
+    VolumeSplit(Vec<ConnectorVolumeSplit>),
+    Advanced(euclid::frontend::ast::Program<ConnectorSelection>),
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+#[serde(tag = "type", content = "data", rename_all = "snake_case")]
+pub enum RoutingAlgorithmSerde {
+    Single(Box<RoutableConnectorChoice>),
+    Priority(Vec<RoutableConnectorChoice>),
+    VolumeSplit(Vec<ConnectorVolumeSplit>),
+    Advanced(euclid::frontend::ast::Program<ConnectorSelection>),
+}
+
+impl TryFrom<RoutingAlgorithmSerde> for RoutingAlgorithm {
+    type Error = error_stack::Report<ParsingError>;
+
+    fn try_from(value: RoutingAlgorithmSerde) -> Result<Self, Self::Error> {
+        match &value {
+            RoutingAlgorithmSerde::Priority(i) if i.is_empty() => {
+                Err(ParsingError::StructParseFailure(
+                    "Connectors list can't be empty for Priority Algorithm",
+                ))
+                .into_report()?
+            }
+            RoutingAlgorithmSerde::VolumeSplit(i) if i.is_empty() => {
+                Err(ParsingError::StructParseFailure(
+                    "Connectors list can't be empty for Volume split Algorithm",
+                ))
+                .into_report()?
+            }
+            _ => {}
+        };
+        Ok(match value {
+            RoutingAlgorithmSerde::Single(i) => Self::Single(i),
+            RoutingAlgorithmSerde::Priority(i) => Self::Priority(i),
+            RoutingAlgorithmSerde::VolumeSplit(i) => Self::VolumeSplit(i),
+            RoutingAlgorithmSerde::Advanced(i) => Self::Advanced(i),
+        })
+    }
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+#[serde(
+    tag = "type",
+    content = "data",
+    rename_all = "snake_case",
+    try_from = "StraightThroughAlgorithmSerde",
+    into = "StraightThroughAlgorithmSerde"
+)]
+pub enum StraightThroughAlgorithm {
+    Single(Box<RoutableConnectorChoice>),
+    Priority(Vec<RoutableConnectorChoice>),
+    VolumeSplit(Vec<ConnectorVolumeSplit>),
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+#[serde(tag = "type", content = "data", rename_all = "snake_case")]
+pub enum StraightThroughAlgorithmInner {
+    Single(Box<RoutableConnectorChoice>),
+    Priority(Vec<RoutableConnectorChoice>),
+    VolumeSplit(Vec<ConnectorVolumeSplit>),
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+#[serde(untagged)]
+pub enum StraightThroughAlgorithmSerde {
+    Direct(StraightThroughAlgorithmInner),
+    Nested {
+        algorithm: StraightThroughAlgorithmInner,
+    },
+}
+
+impl TryFrom<StraightThroughAlgorithmSerde> for StraightThroughAlgorithm {
+    type Error = error_stack::Report<ParsingError>;
+
+    fn try_from(value: StraightThroughAlgorithmSerde) -> Result<Self, Self::Error> {
+        let inner = match value {
+            StraightThroughAlgorithmSerde::Direct(algorithm) => algorithm,
+            StraightThroughAlgorithmSerde::Nested { algorithm } => algorithm,
+        };
+
+        match &inner {
+            StraightThroughAlgorithmInner::Priority(i) if i.is_empty() => {
+                Err(ParsingError::StructParseFailure(
+                    "Connectors list can't be empty for Priority Algorithm",
+                ))
+                .into_report()?
+            }
+            StraightThroughAlgorithmInner::VolumeSplit(i) if i.is_empty() => {
+                Err(ParsingError::StructParseFailure(
+                    "Connectors list can't be empty for Volume split Algorithm",
+                ))
+                .into_report()?
+            }
+            _ => {}
+        };
+
+        Ok(match inner {
+            StraightThroughAlgorithmInner::Single(single) => Self::Single(single),
+            StraightThroughAlgorithmInner::Priority(plist) => Self::Priority(plist),
+            StraightThroughAlgorithmInner::VolumeSplit(vsplit) => Self::VolumeSplit(vsplit),
+        })
+    }
+}
+
+impl From<StraightThroughAlgorithm> for StraightThroughAlgorithmSerde {
+    fn from(value: StraightThroughAlgorithm) -> Self {
+        let inner = match value {
+            StraightThroughAlgorithm::Single(conn) => StraightThroughAlgorithmInner::Single(conn),
+            StraightThroughAlgorithm::Priority(plist) => {
+                StraightThroughAlgorithmInner::Priority(plist)
+            }
+            StraightThroughAlgorithm::VolumeSplit(vsplit) => {
+                StraightThroughAlgorithmInner::VolumeSplit(vsplit)
+            }
+        };
+
+        Self::Nested { algorithm: inner }
+    }
+}
+
+impl From<StraightThroughAlgorithm> for RoutingAlgorithm {
+    fn from(value: StraightThroughAlgorithm) -> Self {
+        match value {
+            StraightThroughAlgorithm::Single(conn) => Self::Single(conn),
+            StraightThroughAlgorithm::Priority(conns) => Self::Priority(conns),
+            StraightThroughAlgorithm::VolumeSplit(splits) => Self::VolumeSplit(splits),
+        }
+    }
+}
+
+impl RoutingAlgorithm {
+    pub fn get_kind(&self) -> RoutingAlgorithmKind {
+        match self {
+            Self::Single(_) => RoutingAlgorithmKind::Single,
+            Self::Priority(_) => RoutingAlgorithmKind::Priority,
+            Self::VolumeSplit(_) => RoutingAlgorithmKind::VolumeSplit,
+            Self::Advanced(_) => RoutingAlgorithmKind::Advanced,
+        }
+    }
+}
+
+#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
+pub struct RoutingAlgorithmRef {
+    pub algorithm_id: Option<String>,
+    pub timestamp: i64,
+    pub config_algo_id: Option<String>,
+    pub surcharge_config_algo_id: Option<String>,
+}
+
+impl RoutingAlgorithmRef {
+    pub fn update_algorithm_id(&mut self, new_id: String) {
+        self.algorithm_id = Some(new_id);
+        self.timestamp = common_utils::date_time::now_unix_timestamp();
+    }
+
+    pub fn update_conditional_config_id(&mut self, ids: String) {
+        self.config_algo_id = Some(ids);
+        self.timestamp = common_utils::date_time::now_unix_timestamp();
+    }
+
+    pub fn update_surcharge_config_id(&mut self, ids: String) {
+        self.surcharge_config_algo_id = Some(ids);
+        self.timestamp = common_utils::date_time::now_unix_timestamp();
+    }
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+
+pub struct RoutingDictionaryRecord {
+    pub id: String,
+    #[cfg(feature = "business_profile_routing")]
+    pub profile_id: String,
+    pub name: String,
+    pub kind: RoutingAlgorithmKind,
+    pub description: String,
+    pub created_at: i64,
+    pub modified_at: i64,
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct RoutingDictionary {
+    pub merchant_id: String,
+    pub active_id: Option<String>,
+    pub records: Vec<RoutingDictionaryRecord>,
+}
+
+#[derive(serde::Serialize, serde::Deserialize, Debug)]
+#[serde(untagged)]
+pub enum RoutingKind {
+    Config(RoutingDictionary),
+    RoutingAlgorithm(Vec<RoutingDictionaryRecord>),
+}
+
+#[repr(transparent)]
+#[derive(serde::Serialize, serde::Deserialize, Debug)]
+#[serde(transparent)]
+pub struct RoutingAlgorithmId(pub String);
diff --git a/crates/api_models/src/user.rs b/crates/api_models/src/user.rs
new file mode 100644
index 000000000000..91f7702c654e
--- /dev/null
+++ b/crates/api_models/src/user.rs
@@ -0,0 +1,21 @@
+use common_utils::pii;
+use masking::Secret;
+
+#[derive(serde::Deserialize, Debug, Clone, serde::Serialize)]
+pub struct ConnectAccountRequest {
+    pub email: pii::Email,
+    pub password: Secret<String>,
+}
+
+#[derive(serde::Serialize, Debug, Clone)]
+pub struct ConnectAccountResponse {
+    pub token: Secret<String>,
+    pub merchant_id: String,
+    pub name: Secret<String>,
+    pub email: pii::Email,
+    pub verification_days_left: Option<i64>,
+    pub user_role: String,
+    //this field is added for audit/debug reasons
+    #[serde(skip_serializing)]
+    pub user_id: String,
+}
diff --git a/crates/common_enums/Cargo.toml b/crates/common_enums/Cargo.toml
index 10b4fb509e88..88628825ca64 100644
--- a/crates/common_enums/Cargo.toml
+++ b/crates/common_enums/Cargo.toml
@@ -7,19 +7,14 @@ rust-version.workspace = true
 readme = "README.md"
 license.workspace = true
 
-[features]
-dummy_connector = []
-
 [dependencies]
 diesel = { version = "2.1.0", features = ["postgres"] }
-serde  = { version = "1.0.160", features = [ "derive" ] }
+serde = { version = "1.0.160", features = ["derive"] }
 serde_json = "1.0.96"
-strum  = { version = "0.25", features = [ "derive" ] }
-time = { version = "0.3.21", features = ["serde", "serde-well-known", "std"] }
+strum = { version = "0.25", features = ["derive"] }
 utoipa = { version = "3.3.0", features = ["preserve_order"] }
 
 # First party crates
-common_utils = { version = "0.1.0", path = "../common_utils" }
 router_derive = { version = "0.1.0", path = "../router_derive" }
 
 [dev-dependencies]
diff --git a/crates/common_utils/Cargo.toml b/crates/common_utils/Cargo.toml
index e319cf86ccd0..3619c93d772c 100644
--- a/crates/common_utils/Cargo.toml
+++ b/crates/common_utils/Cargo.toml
@@ -23,11 +23,13 @@ http = "0.2.9"
 md5 = "0.7.0"
 nanoid = "0.4.0"
 once_cell = "1.18.0"
+phonenumber = "0.3.3"
 quick-xml = { version = "0.28.2", features = ["serialize"] }
 rand = "0.8.5"
 regex = "1.8.4"
 reqwest = { version = "0.11.18", features = ["json", "native-tls", "gzip", "multipart"] }
 ring = { version = "0.16.20", features = ["std"] }
+rustc-hash = "1.1.0"
 serde = { version = "1.0.163", features = ["derive"] }
 serde_json = "1.0.96"
 serde_urlencoded = "0.7.1"
@@ -36,9 +38,9 @@ strum = { version = "0.24.1", features = ["derive"] }
 thiserror = "1.0.40"
 time = { version = "0.3.21", features = ["serde", "serde-well-known", "std"] }
 tokio = { version = "1.28.2", features = ["macros", "rt-multi-thread"], optional = true }
-phonenumber = "0.3.3"
 
 # First party crates
+common_enums = { version = "0.1.0", path = "../common_enums" }
 masking = { version = "0.1.0", path = "../masking" }
 router_env = { version = "0.1.0", path = "../router_env", features = ["log_extra_implicit_fields", "log_custom_entries_to_extra"], optional = true }
 
diff --git a/crates/common_utils/src/consts.rs b/crates/common_utils/src/consts.rs
index c3f159956fc0..60756192d66e 100644
--- a/crates/common_utils/src/consts.rs
+++ b/crates/common_utils/src/consts.rs
@@ -30,6 +30,18 @@ pub const SURCHARGE_PERCENTAGE_PRECISION_LENGTH: u8 = 2;
 /// Header Key for application overhead of a request
 pub const X_HS_LATENCY: &str = "x-hs-latency";
 
+/// SDK Default Theme const
+pub const DEFAULT_SDK_THEME: &str = "#7EA8F6";
+
+/// Default Payment Link Background color
+pub const DEFAULT_BACKGROUND_COLOR: &str = "#E5E5E5";
+
+/// Default product Img Link
+pub const DEFAULT_PRODUCT_IMG: &str = "https://i.imgur.com/On3VtKF.png";
+
+/// Default Merchant Logo Link
+pub const DEFAULT_MERCHANT_LOGO: &str = "https://i.imgur.com/RfxPFQo.png";
+
 /// Redirect url for Prophetpay
 pub const PROPHETPAY_REDIRECT_URL: &str = "https://ccm-thirdparty.cps.golf/hp/tokenize/";
 
diff --git a/crates/common_utils/src/custom_serde.rs b/crates/common_utils/src/custom_serde.rs
index d64abe38e5b0..edbfa143a667 100644
--- a/crates/common_utils/src/custom_serde.rs
+++ b/crates/common_utils/src/custom_serde.rs
@@ -170,3 +170,51 @@ pub mod json_string {
         serde_json::from_str(&j).map_err(de::Error::custom)
     }
 }
+
+/// Use a custom ISO 8601 format when serializing and deserializing
+/// [`PrimitiveDateTime`][PrimitiveDateTime].
+///
+/// [PrimitiveDateTime]: ::time::PrimitiveDateTime
+pub mod iso8601custom {
+
+    use serde::{ser::Error as _, Deserializer, Serialize, Serializer};
+    use time::{
+        format_description::well_known::{
+            iso8601::{Config, EncodedConfig, TimePrecision},
+            Iso8601,
+        },
+        serde::iso8601,
+        PrimitiveDateTime, UtcOffset,
+    };
+
+    const FORMAT_CONFIG: EncodedConfig = Config::DEFAULT
+        .set_time_precision(TimePrecision::Second {
+            decimal_digits: None,
+        })
+        .encode();
+
+    /// Serialize a [`PrimitiveDateTime`] using the well-known ISO 8601 format.
+    pub fn serialize<S>(date_time: &PrimitiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        date_time
+            .assume_utc()
+            .format(&Iso8601::<FORMAT_CONFIG>)
+            .map_err(S::Error::custom)?
+            .replace('T', " ")
+            .replace('Z', "")
+            .serialize(serializer)
+    }
+
+    /// Deserialize an [`PrimitiveDateTime`] from its ISO 8601 representation.
+    pub fn deserialize<'a, D>(deserializer: D) -> Result<PrimitiveDateTime, D::Error>
+    where
+        D: Deserializer<'a>,
+    {
+        iso8601::deserialize(deserializer).map(|offset_date_time| {
+            let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
+            PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
+        })
+    }
+}
diff --git a/crates/common_utils/src/errors.rs b/crates/common_utils/src/errors.rs
index 6541633a56ee..7f3430657058 100644
--- a/crates/common_utils/src/errors.rs
+++ b/crates/common_utils/src/errors.rs
@@ -77,11 +77,20 @@ pub enum QrCodeError {
 }
 
 /// Api Models construction error
-#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
-pub enum ApiModelsError {
+#[derive(Debug, Clone, thiserror::Error, PartialEq)]
+pub enum PercentageError {
     /// Percentage Value provided was invalid
     #[error("Invalid Percentage value")]
     InvalidPercentageValue,
+
+    /// Error occurred while calculating percentage
+    #[error("Failed apply percentage of {percentage} on {amount}")]
+    UnableToApplyPercentage {
+        /// percentage value
+        percentage: f32,
+        /// amount value
+        amount: i64,
+    },
 }
 
 /// Allows [error_stack::Report] to change between error contexts
diff --git a/crates/common_utils/src/events.rs b/crates/common_utils/src/events.rs
new file mode 100644
index 000000000000..753f1deeb676
--- /dev/null
+++ b/crates/common_utils/src/events.rs
@@ -0,0 +1,92 @@
+use common_enums::{PaymentMethod, PaymentMethodType};
+use serde::Serialize;
+
+pub trait ApiEventMetric {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        None
+    }
+}
+
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
+#[serde(tag = "flow_type", rename_all = "snake_case")]
+pub enum ApiEventsType {
+    Payout,
+    Payment {
+        payment_id: String,
+    },
+    Refund {
+        payment_id: Option<String>,
+        refund_id: String,
+    },
+    PaymentMethod {
+        payment_method_id: String,
+        payment_method: Option<PaymentMethod>,
+        payment_method_type: Option<PaymentMethodType>,
+    },
+    Customer {
+        customer_id: String,
+    },
+    User {
+        //specified merchant_id will overridden on global defined
+        merchant_id: String,
+        user_id: String,
+    },
+    PaymentMethodList {
+        payment_id: Option<String>,
+    },
+    Webhooks {
+        connector: String,
+        payment_id: Option<String>,
+    },
+    Routing,
+    ResourceListAPI,
+    PaymentRedirectionResponse,
+    Gsm,
+    // TODO: This has to be removed once the corresponding apiEventTypes are created
+    Miscellaneous,
+}
+
+impl ApiEventMetric for serde_json::Value {}
+impl ApiEventMetric for () {}
+
+impl<Q: ApiEventMetric, E> ApiEventMetric for Result<Q, E> {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        match self {
+            Ok(q) => q.get_api_event_type(),
+            Err(_) => None,
+        }
+    }
+}
+
+// TODO: Ideally all these types should be replaced by newtype responses
+impl<T> ApiEventMetric for Vec<T> {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Miscellaneous)
+    }
+}
+
+#[macro_export]
+macro_rules! impl_misc_api_event_type {
+    ($($type:ty),+) => {
+        $(
+            impl ApiEventMetric for $type {
+                fn get_api_event_type(&self) -> Option<ApiEventsType> {
+                    Some(ApiEventsType::Miscellaneous)
+                }
+            }
+        )+
+     };
+}
+
+impl_misc_api_event_type!(
+    String,
+    (&String, &String),
+    (Option<i64>, Option<i64>, String),
+    bool
+);
+
+impl<T: ApiEventMetric> ApiEventMetric for &T {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        T::get_api_event_type(self)
+    }
+}
diff --git a/crates/common_utils/src/lib.rs b/crates/common_utils/src/lib.rs
index ca6bba480063..62428dccfb6a 100644
--- a/crates/common_utils/src/lib.rs
+++ b/crates/common_utils/src/lib.rs
@@ -6,6 +6,8 @@ pub mod consts;
 pub mod crypto;
 pub mod custom_serde;
 pub mod errors;
+#[allow(missing_docs)] // Todo: add docs
+pub mod events;
 pub mod ext_traits;
 pub mod fp_utils;
 pub mod pii;
@@ -13,6 +15,8 @@ pub mod pii;
 pub mod request;
 #[cfg(feature = "signals")]
 pub mod signals;
+#[allow(missing_docs)] // Todo: add docs
+pub mod static_cache;
 pub mod types;
 pub mod validation;
 
diff --git a/crates/common_utils/src/static_cache.rs b/crates/common_utils/src/static_cache.rs
new file mode 100644
index 000000000000..ca608fa9a3b5
--- /dev/null
+++ b/crates/common_utils/src/static_cache.rs
@@ -0,0 +1,91 @@
+use std::sync::{Arc, RwLock};
+
+use once_cell::sync::Lazy;
+use rustc_hash::FxHashMap;
+
+#[derive(Debug)]
+pub struct CacheEntry<T> {
+    data: Arc<T>,
+    timestamp: i64,
+}
+
+#[derive(Debug, Clone, thiserror::Error)]
+pub enum CacheError {
+    #[error("Could not acquire the lock for cache entry")]
+    CouldNotAcquireLock,
+    #[error("Entry not found in cache")]
+    EntryNotFound,
+}
+
+#[derive(Debug)]
+pub struct StaticCache<T> {
+    data: Lazy<RwLock<FxHashMap<String, CacheEntry<T>>>>,
+}
+
+impl<T> StaticCache<T>
+where
+    T: Send,
+{
+    pub const fn new() -> Self {
+        Self {
+            data: Lazy::new(|| RwLock::new(FxHashMap::default())),
+        }
+    }
+
+    pub fn present(&self, key: &String) -> Result<bool, CacheError> {
+        let the_map = self
+            .data
+            .read()
+            .map_err(|_| CacheError::CouldNotAcquireLock)?;
+
+        Ok(the_map.get(key).is_some())
+    }
+
+    pub fn expired(&self, key: &String, timestamp: i64) -> Result<bool, CacheError> {
+        let the_map = self
+            .data
+            .read()
+            .map_err(|_| CacheError::CouldNotAcquireLock)?;
+
+        Ok(match the_map.get(key) {
+            None => false,
+            Some(entry) => timestamp > entry.timestamp,
+        })
+    }
+
+    pub fn retrieve(&self, key: &String) -> Result<Arc<T>, CacheError> {
+        let the_map = self
+            .data
+            .read()
+            .map_err(|_| CacheError::CouldNotAcquireLock)?;
+
+        let cache_entry = the_map.get(key).ok_or(CacheError::EntryNotFound)?;
+
+        Ok(Arc::clone(&cache_entry.data))
+    }
+
+    pub fn save(&self, key: String, data: T, timestamp: i64) -> Result<(), CacheError> {
+        let mut the_map = self
+            .data
+            .write()
+            .map_err(|_| CacheError::CouldNotAcquireLock)?;
+
+        let entry = CacheEntry {
+            data: Arc::new(data),
+            timestamp,
+        };
+
+        the_map.insert(key, entry);
+        Ok(())
+    }
+
+    pub fn clear(&self) -> Result<(), CacheError> {
+        let mut the_map = self
+            .data
+            .write()
+            .map_err(|_| CacheError::CouldNotAcquireLock)?;
+
+        the_map.clear();
+        Ok(())
+    }
+}
diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs
index d745334a21ea..111f0f43c0f2 100644
--- a/crates/common_utils/src/types.rs
+++ b/crates/common_utils/src/types.rs
@@ -2,7 +2,7 @@
 use error_stack::{IntoReport, ResultExt};
 use serde::{de::Visitor, Deserialize, Deserializer};
 
-use crate::errors::{ApiModelsError, CustomResult};
+use crate::errors::{CustomResult, PercentageError};
 
 /// Represents Percentage Value between 0 and 100 both inclusive
 #[derive(Clone, Default, Debug, PartialEq, serde::Serialize)]
@@ -21,16 +21,16 @@ fn get_invalid_percentage_error_message(precision: u8) -> String {
 
 impl<const PRECISION: u8> Percentage<PRECISION> {
     /// construct percentage using a string representation of float value
-    pub fn from_string(value: String) -> CustomResult<Self, ApiModelsError> {
+    pub fn from_string(value: String) -> CustomResult<Self, PercentageError> {
         if Self::is_valid_string_value(&value)? {
             Ok(Self {
                 percentage: value
                     .parse()
                     .into_report()
-                    .change_context(ApiModelsError::InvalidPercentageValue)?,
+                    .change_context(PercentageError::InvalidPercentageValue)?,
             })
         } else {
-            Err(ApiModelsError::InvalidPercentageValue.into())
+            Err(PercentageError::InvalidPercentageValue.into())
                 .attach_printable(get_invalid_percentage_error_message(PRECISION))
         }
     }
@@ -38,15 +38,37 @@ impl<const PRECISION: u8> Percentage<PRECISION> {
     pub fn get_percentage(&self) -> f32 {
         self.percentage
     }
-    fn is_valid_string_value(value: &str) -> CustomResult<bool, ApiModelsError> {
+
+    /// apply the percentage to amount and ceil the result
+    #[allow(clippy::as_conversions)]
+    pub fn apply_and_ceil_result(&self, amount: i64) -> CustomResult<i64, PercentageError> {
+        let max_amount = i64::MAX / 10000;
+        if amount > max_amount {
+            // value gets rounded off after i64::MAX/10000
+            Err(PercentageError::UnableToApplyPercentage {
+                percentage: self.percentage,
+                amount,
+            }
+            .into())
+            .attach_printable(format!(
+                "Cannot calculate percentage for amount greater than {}",
+                max_amount
+            ))
+        } else {
+            let percentage_f64 = f64::from(self.percentage);
+            let result = (amount as f64 * (percentage_f64 / 100.0)).ceil() as i64;
+            Ok(result)
+        }
+    }
+    fn is_valid_string_value(value: &str) -> CustomResult<bool, PercentageError> {
         let float_value = Self::is_valid_float_string(value)?;
         Ok(Self::is_valid_range(float_value) && Self::is_valid_precision_length(value))
     }
-    fn is_valid_float_string(value: &str) -> CustomResult<f32, ApiModelsError> {
+    fn is_valid_float_string(value: &str) -> CustomResult<f32, PercentageError> {
         value
             .parse()
             .into_report()
-            .change_context(ApiModelsError::InvalidPercentageValue)
+            .change_context(PercentageError::InvalidPercentageValue)
     }
     fn is_valid_range(value: f32) -> bool {
         (0.0..=100.0).contains(&value)
@@ -55,7 +77,9 @@ impl<const PRECISION: u8> Percentage<PRECISION> {
         if value.contains('.') {
             // if string has '.' then take the decimal part and verify precision length
             match value.split('.').last() {
-                Some(decimal_part) => decimal_part.trim_end_matches('0').len() <= PRECISION.into(),
+                Some(decimal_part) => {
+                    decimal_part.trim_end_matches('0').len() <= <u8 as Into<usize>>::into(PRECISION)
+                }
                 // will never be None
                 None => false,
             }
diff --git a/crates/common_utils/tests/percentage.rs b/crates/common_utils/tests/percentage.rs
index 95c112523376..0858c98fd63a 100644
--- a/crates/common_utils/tests/percentage.rs
+++ b/crates/common_utils/tests/percentage.rs
@@ -1,5 +1,5 @@
 #![allow(clippy::panic_in_result_fn)]
-use common_utils::{errors::ApiModelsError, types::Percentage};
+use common_utils::{errors::PercentageError, types::Percentage};
 const PRECISION_2: u8 = 2;
 const PRECISION_0: u8 = 0;
 
@@ -10,7 +10,7 @@ fn invalid_range_more_than_100() -> Result<(), Box<dyn std::error::Error + Send
     if let Err(err) = percentage {
         assert_eq!(
             *err.current_context(),
-            ApiModelsError::InvalidPercentageValue
+            PercentageError::InvalidPercentageValue
         )
     }
     Ok(())
@@ -22,7 +22,7 @@ fn invalid_range_less_than_0() -> Result<(), Box<dyn std::error::Error + Send +
     if let Err(err) = percentage {
         assert_eq!(
             *err.current_context(),
-            ApiModelsError::InvalidPercentageValue
+            PercentageError::InvalidPercentageValue
         )
     }
     Ok(())
@@ -35,7 +35,7 @@ fn invalid_string() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
     if let Err(err) = percentage {
         assert_eq!(
             *err.current_context(),
-            ApiModelsError::InvalidPercentageValue
+            PercentageError::InvalidPercentageValue
         )
     }
     Ok(())
@@ -92,7 +92,7 @@ fn invalid_precision() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
     if let Err(err) = percentage {
         assert_eq!(
             *err.current_context(),
-            ApiModelsError::InvalidPercentageValue
+            PercentageError::InvalidPercentageValue
         )
     }
     Ok(())
diff --git a/crates/data_models/Cargo.toml b/crates/data_models/Cargo.toml
index 254c194182f3..57ae1ec1ec87 100644
--- a/crates/data_models/Cargo.toml
+++ b/crates/data_models/Cargo.toml
@@ -8,16 +8,15 @@ readme = "README.md"
 license.workspace = true
 
 [features]
-default = ["olap", "oltp"]
-oltp = []
+default = ["olap"]
 olap = []
 
 [dependencies]
 # First party deps
 api_models = { version = "0.1.0", path = "../api_models" }
-masking = { version = "0.1.0", path = "../masking" }
 common_enums = { version = "0.1.0", path = "../common_enums" }
 common_utils = { version = "0.1.0", path = "../common_utils" }
+masking = { version = "0.1.0", path = "../masking" }
 
 
 # Third party deps
@@ -25,6 +24,5 @@ async-trait = "0.1.68"
 error-stack = "0.3.1"
 serde = { version = "1.0.163", features = ["derive"] }
 serde_json = "1.0.96"
-strum  = { version = "0.25", features = [ "derive" ] }
 thiserror = "1.0.40"
-time = { version = "0.3.21", features = ["serde", "serde-well-known", "std"] }
\ No newline at end of file
+time = { version = "0.3.21", features = ["serde", "serde-well-known", "std"] }
diff --git a/crates/data_models/src/payments.rs b/crates/data_models/src/payments.rs
index 029f7108507e..4e7a0923f6a9 100644
--- a/crates/data_models/src/payments.rs
+++ b/crates/data_models/src/payments.rs
@@ -47,5 +47,7 @@ pub struct PaymentIntent {
     // Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment
     pub merchant_decision: Option<String>,
     pub payment_confirm_source: Option<storage_enums::PaymentSource>,
+
     pub updated_by: String,
+    pub surcharge_applicable: Option<bool>,
 }
diff --git a/crates/data_models/src/payments/payment_attempt.rs b/crates/data_models/src/payments/payment_attempt.rs
index c31230229de4..88fc7b3b524a 100644
--- a/crates/data_models/src/payments/payment_attempt.rs
+++ b/crates/data_models/src/payments/payment_attempt.rs
@@ -141,8 +141,10 @@ pub struct PaymentAttempt {
     // reference to the payment at connector side
     pub connector_response_reference_id: Option<String>,
     pub amount_capturable: i64,
-    pub surcharge_metadata: Option<serde_json::Value>,
     pub updated_by: String,
+    pub authentication_data: Option<serde_json::Value>,
+    pub encoded_data: Option<String>,
+    pub merchant_connector_id: Option<String>,
 }
 
 #[derive(Clone, Debug, Eq, PartialEq)]
@@ -201,8 +203,10 @@ pub struct PaymentAttemptNew {
     pub connector_response_reference_id: Option<String>,
     pub multiple_capture_count: Option<i16>,
     pub amount_capturable: i64,
-    pub surcharge_metadata: Option<serde_json::Value>,
     pub updated_by: String,
+    pub authentication_data: Option<serde_json::Value>,
+    pub encoded_data: Option<String>,
+    pub merchant_connector_id: Option<String>,
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -220,6 +224,8 @@ pub enum PaymentAttemptUpdate {
         business_sub_label: Option<String>,
         amount_to_capture: Option<i64>,
         capture_method: Option<storage_enums::CaptureMethod>,
+        surcharge_amount: Option<i64>,
+        tax_amount: Option<i64>,
         updated_by: String,
     },
     UpdateTrackers {
@@ -227,7 +233,10 @@ pub enum PaymentAttemptUpdate {
         connector: Option<String>,
         straight_through_algorithm: Option<serde_json::Value>,
         amount_capturable: Option<i64>,
+        surcharge_amount: Option<i64>,
+        tax_amount: Option<i64>,
         updated_by: String,
+        merchant_connector_id: Option<String>,
     },
     AuthenticationTypeUpdate {
         authentication_type: storage_enums::AuthenticationType,
@@ -250,9 +259,8 @@ pub enum PaymentAttemptUpdate {
         error_code: Option<Option<String>>,
         error_message: Option<Option<String>>,
         amount_capturable: Option<i64>,
-        surcharge_amount: Option<i64>,
-        tax_amount: Option<i64>,
         updated_by: String,
+        merchant_connector_id: Option<String>,
     },
     RejectUpdate {
         status: storage_enums::AttemptStatus,
@@ -279,7 +287,11 @@ pub enum PaymentAttemptUpdate {
         error_reason: Option<Option<String>>,
         connector_response_reference_id: Option<String>,
         amount_capturable: Option<i64>,
+        surcharge_amount: Option<i64>,
+        tax_amount: Option<i64>,
         updated_by: String,
+        authentication_data: Option<serde_json::Value>,
+        encoded_data: Option<String>,
     },
     UnresolvedResponseUpdate {
         status: storage_enums::AttemptStatus,
@@ -323,8 +335,11 @@ pub enum PaymentAttemptUpdate {
         connector_response_reference_id: Option<String>,
         updated_by: String,
     },
-    SurchargeMetadataUpdate {
-        surcharge_metadata: Option<serde_json::Value>,
+    ConnectorResponse {
+        authentication_data: Option<serde_json::Value>,
+        encoded_data: Option<String>,
+        connector_transaction_id: Option<String>,
+        connector: Option<String>,
         updated_by: String,
     },
 }
diff --git a/crates/data_models/src/payments/payment_intent.rs b/crates/data_models/src/payments/payment_intent.rs
index 155e6b5ca679..2c5914f5b37f 100644
--- a/crates/data_models/src/payments/payment_intent.rs
+++ b/crates/data_models/src/payments/payment_intent.rs
@@ -104,7 +104,9 @@ pub struct PaymentIntentNew {
     pub merchant_decision: Option<String>,
     pub payment_link_id: Option<String>,
     pub payment_confirm_source: Option<storage_enums::PaymentSource>,
+
     pub updated_by: String,
+    pub surcharge_applicable: Option<bool>,
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -176,6 +178,10 @@ pub enum PaymentIntentUpdate {
         merchant_decision: Option<String>,
         updated_by: String,
     },
+    SurchargeApplicableUpdate {
+        surcharge_applicable: bool,
+        updated_by: String,
+    },
 }
 
 #[derive(Clone, Debug, Default)]
@@ -204,36 +210,9 @@ pub struct PaymentIntentUpdateInternal {
     // Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment
     pub merchant_decision: Option<String>,
     pub payment_confirm_source: Option<storage_enums::PaymentSource>,
-    pub updated_by: String,
-}
 
-impl PaymentIntentUpdate {
-    pub fn apply_changeset(self, source: PaymentIntent) -> PaymentIntent {
-        let internal_update: PaymentIntentUpdateInternal = self.into();
-        PaymentIntent {
-            amount: internal_update.amount.unwrap_or(source.amount),
-            currency: internal_update.currency.or(source.currency),
-            status: internal_update.status.unwrap_or(source.status),
-            amount_captured: internal_update.amount_captured.or(source.amount_captured),
-            customer_id: internal_update.customer_id.or(source.customer_id),
-            return_url: internal_update.return_url.or(source.return_url),
-            setup_future_usage: internal_update
-                .setup_future_usage
-                .or(source.setup_future_usage),
-            off_session: internal_update.off_session.or(source.off_session),
-            metadata: internal_update.metadata.or(source.metadata),
-            billing_address_id: internal_update
-                .billing_address_id
-                .or(source.billing_address_id),
-            shipping_address_id: internal_update
-                .shipping_address_id
-                .or(source.shipping_address_id),
-            modified_at: common_utils::date_time::now(),
-            order_details: internal_update.order_details.or(source.order_details),
-            updated_by: internal_update.updated_by,
-            ..source
-        }
-    }
+    pub updated_by: String,
+    pub surcharge_applicable: Option<bool>,
 }
 
 impl From<PaymentIntentUpdate> for PaymentIntentUpdateInternal {
@@ -382,6 +361,14 @@ impl From<PaymentIntentUpdate> for PaymentIntentUpdateInternal {
                 updated_by,
                 ..Default::default()
             },
+            PaymentIntentUpdate::SurchargeApplicableUpdate {
+                surcharge_applicable,
+                updated_by,
+            } => Self {
+                surcharge_applicable: Some(surcharge_applicable),
+                updated_by,
+                ..Default::default()
+            },
         }
     }
 }
diff --git a/crates/diesel_models/Cargo.toml b/crates/diesel_models/Cargo.toml
index 1a0bdfe5674e..ccef0bf4e742 100644
--- a/crates/diesel_models/Cargo.toml
+++ b/crates/diesel_models/Cargo.toml
@@ -9,15 +9,10 @@ license.workspace = true
 
 [features]
 default = ["kv_store"]
-email = ["external_services/email", "dep:aws-config"]
-kms = ["external_services/kms", "dep:aws-config"]
 kv_store = []
-s3 = ["dep:aws-sdk-s3", "dep:aws-config"]
 
 [dependencies]
-async-bb8-diesel = "0.1.0"
-aws-config = { version = "0.55.3", optional = true }
-aws-sdk-s3 = { version = "0.28.0", optional = true }
+async-bb8-diesel = { git = "https://github.com/jarnura/async-bb8-diesel", rev = "53b4ab901aab7635c8215fd1c2d542c8db443094" }
 diesel = { version = "2.1.0", features = ["postgres", "serde_json", "time", "64-column-tables"] }
 error-stack = "0.3.1"
 frunk = "0.4.1"
@@ -31,7 +26,6 @@ time = { version = "0.3.21", features = ["serde", "serde-well-known", "std"] }
 # First party crates
 common_enums = { path = "../common_enums" }
 common_utils = { version = "0.1.0", path = "../common_utils" }
-external_services = { version = "0.1.0", path = "../external_services" }
 masking = { version = "0.1.0", path = "../masking" }
 router_derive = { version = "0.1.0", path = "../router_derive" }
 router_env = { version = "0.1.0", path = "../router_env", features = ["log_extra_implicit_fields", "log_custom_entries_to_extra"] }
diff --git a/crates/diesel_models/src/address.rs b/crates/diesel_models/src/address.rs
index e67f37c90465..03dedfd60d8f 100644
--- a/crates/diesel_models/src/address.rs
+++ b/crates/diesel_models/src/address.rs
@@ -19,7 +19,7 @@ pub struct AddressNew {
     pub last_name: Option<Encryption>,
     pub phone_number: Option<Encryption>,
     pub country_code: Option<String>,
-    pub customer_id: String,
+    pub customer_id: Option<String>,
     pub merchant_id: String,
     pub payment_id: Option<String>,
     pub created_at: PrimitiveDateTime,
@@ -45,7 +45,7 @@ pub struct Address {
     pub country_code: Option<String>,
     pub created_at: PrimitiveDateTime,
     pub modified_at: PrimitiveDateTime,
-    pub customer_id: String,
+    pub customer_id: Option<String>,
     pub merchant_id: String,
     pub payment_id: Option<String>,
     pub updated_by: String,
diff --git a/crates/diesel_models/src/connector_response.rs b/crates/diesel_models/src/connector_response.rs
deleted file mode 100644
index 863ce28ee0ae..000000000000
--- a/crates/diesel_models/src/connector_response.rs
+++ /dev/null
@@ -1,122 +0,0 @@
-use diesel::{AsChangeset, Identifiable, Insertable, Queryable};
-use serde::{Deserialize, Serialize};
-use time::PrimitiveDateTime;
-
-use crate::schema::connector_response;
-
-#[derive(Clone, Debug, Deserialize, Serialize, Insertable, router_derive::DebugAsDisplay)]
-#[diesel(table_name = connector_response)]
-#[serde(deny_unknown_fields)]
-pub struct ConnectorResponseNew {
-    pub payment_id: String,
-    pub merchant_id: String,
-    pub attempt_id: String,
-    #[serde(with = "common_utils::custom_serde::iso8601")]
-    pub created_at: PrimitiveDateTime,
-    #[serde(with = "common_utils::custom_serde::iso8601")]
-    pub modified_at: PrimitiveDateTime,
-    pub connector_name: Option<String>,
-    pub connector_transaction_id: Option<String>,
-    pub authentication_data: Option<serde_json::Value>,
-    pub encoded_data: Option<String>,
-    pub updated_by: String,
-}
-
-#[derive(Clone, Debug, Deserialize, Serialize, Identifiable, Queryable)]
-#[diesel(table_name = connector_response)]
-pub struct ConnectorResponse {
-    pub id: i32,
-    pub payment_id: String,
-    pub merchant_id: String,
-    pub attempt_id: String,
-    #[serde(with = "common_utils::custom_serde::iso8601")]
-    pub created_at: PrimitiveDateTime,
-    #[serde(with = "common_utils::custom_serde::iso8601")]
-    pub modified_at: PrimitiveDateTime,
-    pub connector_name: Option<String>,
-    pub connector_transaction_id: Option<String>,
-    pub authentication_data: Option<serde_json::Value>,
-    pub encoded_data: Option<String>,
-    pub updated_by: String,
-}
-
-#[derive(Clone, Default, Debug, Deserialize, AsChangeset, Serialize)]
-#[diesel(table_name = connector_response)]
-pub struct ConnectorResponseUpdateInternal {
-    pub connector_transaction_id: Option<String>,
-    pub authentication_data: Option<serde_json::Value>,
-    pub modified_at: Option<PrimitiveDateTime>,
-    pub encoded_data: Option<String>,
-    pub connector_name: Option<String>,
-    pub updated_by: String,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize)]
-pub enum ConnectorResponseUpdate {
-    ResponseUpdate {
-        connector_transaction_id: Option<String>,
-        authentication_data: Option<serde_json::Value>,
-        encoded_data: Option<String>,
-        connector_name: Option<String>,
-        updated_by: String,
-    },
-    ErrorUpdate {
-        connector_name: Option<String>,
-        updated_by: String,
-    },
-}
-
-impl ConnectorResponseUpdate {
-    pub fn apply_changeset(self, source: ConnectorResponse) -> ConnectorResponse {
-        let connector_response_update: ConnectorResponseUpdateInternal = self.into();
-        ConnectorResponse {
-            modified_at: connector_response_update
-                .modified_at
-                .unwrap_or_else(common_utils::date_time::now),
-            connector_name: connector_response_update
-                .connector_name
-                .or(source.connector_name),
-            connector_transaction_id: source
-                .connector_transaction_id
-                .or(connector_response_update.connector_transaction_id),
-            authentication_data: connector_response_update
-                .authentication_data
-                .or(source.authentication_data),
-            encoded_data: connector_response_update
-                .encoded_data
-                .or(source.encoded_data),
-            updated_by: connector_response_update.updated_by,
-            ..source
-        }
-    }
-}
-
-impl From<ConnectorResponseUpdate> for ConnectorResponseUpdateInternal {
-    fn from(connector_response_update: ConnectorResponseUpdate) -> Self {
-        match connector_response_update {
-            ConnectorResponseUpdate::ResponseUpdate {
-                connector_transaction_id,
-                authentication_data,
-                encoded_data,
-                connector_name,
-                updated_by,
-            } => Self {
-                connector_transaction_id,
-                authentication_data,
-                encoded_data,
-                modified_at: Some(common_utils::date_time::now()),
-                connector_name,
-                updated_by,
-            },
-            ConnectorResponseUpdate::ErrorUpdate {
-                connector_name,
-                updated_by,
-            } => Self {
-                connector_name,
-                modified_at: Some(common_utils::date_time::now()),
-                updated_by,
-                ..Self::default()
-            },
-        }
-    }
-}
diff --git a/crates/diesel_models/src/dispute.rs b/crates/diesel_models/src/dispute.rs
index 1e1609491fe8..9bdac3322952 100644
--- a/crates/diesel_models/src/dispute.rs
+++ b/crates/diesel_models/src/dispute.rs
@@ -28,6 +28,7 @@ pub struct DisputeNew {
     pub connector: String,
     pub evidence: Option<Secret<serde_json::Value>>,
     pub profile_id: Option<String>,
+    pub merchant_connector_id: Option<String>,
 }
 
 #[derive(Clone, Debug, PartialEq, Serialize, Identifiable, Queryable)]
@@ -57,6 +58,7 @@ pub struct Dispute {
     pub connector: String,
     pub evidence: Secret<serde_json::Value>,
     pub profile_id: Option<String>,
+    pub merchant_connector_id: Option<String>,
 }
 
 #[derive(Debug)]
diff --git a/crates/diesel_models/src/enums.rs b/crates/diesel_models/src/enums.rs
index b73eeefbb10b..ec021f0f51a5 100644
--- a/crates/diesel_models/src/enums.rs
+++ b/crates/diesel_models/src/enums.rs
@@ -14,6 +14,7 @@ pub mod diesel_exports {
         DbPaymentType as PaymentType, DbPayoutStatus as PayoutStatus, DbPayoutType as PayoutType,
         DbProcessTrackerStatus as ProcessTrackerStatus, DbReconStatus as ReconStatus,
         DbRefundStatus as RefundStatus, DbRefundType as RefundType,
+        DbRoutingAlgorithmKind as RoutingAlgorithmKind,
     };
 }
 pub use common_enums::*;
@@ -21,6 +22,27 @@ use common_utils::pii;
 use diesel::serialize::{Output, ToSql};
 use time::PrimitiveDateTime;
 
+#[derive(
+    Clone,
+    Copy,
+    Debug,
+    Eq,
+    PartialEq,
+    serde::Deserialize,
+    serde::Serialize,
+    strum::Display,
+    strum::EnumString,
+)]
+#[router_derive::diesel_enum(storage_type = "pg_enum")]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum RoutingAlgorithmKind {
+    Single,
+    Priority,
+    VolumeSplit,
+    Advanced,
+}
+
 #[derive(
     Clone,
     Copy,
@@ -379,3 +401,25 @@ pub enum FraudCheckLastStep {
     TransactionOrRecordRefund,
     Fulfillment,
 }
+
+#[derive(
+    Clone,
+    Copy,
+    Debug,
+    Default,
+    Eq,
+    PartialEq,
+    serde::Serialize,
+    serde::Deserialize,
+    strum::Display,
+    strum::EnumString,
+    frunk::LabelledGeneric,
+)]
+#[router_derive::diesel_enum(storage_type = "text")]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum UserStatus {
+    Active,
+    #[default]
+    InvitationSent,
+}
diff --git a/crates/diesel_models/src/ephemeral_key.rs b/crates/diesel_models/src/ephemeral_key.rs
index 96bd6e497c33..77b9c647e43b 100644
--- a/crates/diesel_models/src/ephemeral_key.rs
+++ b/crates/diesel_models/src/ephemeral_key.rs
@@ -14,3 +14,9 @@ pub struct EphemeralKey {
     pub expires: i64,
     pub secret: String,
 }
+
+impl common_utils::events::ApiEventMetric for EphemeralKey {
+    fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
+        Some(common_utils::events::ApiEventsType::Miscellaneous)
+    }
+}
diff --git a/crates/diesel_models/src/file.rs b/crates/diesel_models/src/file.rs
index d6efcbbc6a9d..20150a6928d9 100644
--- a/crates/diesel_models/src/file.rs
+++ b/crates/diesel_models/src/file.rs
@@ -18,6 +18,7 @@ pub struct FileMetadataNew {
     pub available: bool,
     pub connector_label: Option<String>,
     pub profile_id: Option<String>,
+    pub merchant_connector_id: Option<String>,
 }
 
 #[derive(Clone, Debug, Deserialize, Serialize, Identifiable, Queryable)]
@@ -36,6 +37,7 @@ pub struct FileMetadata {
     pub created_at: time::PrimitiveDateTime,
     pub connector_label: Option<String>,
     pub profile_id: Option<String>,
+    pub merchant_connector_id: Option<String>,
 }
 
 #[derive(Debug)]
@@ -44,7 +46,8 @@ pub enum FileMetadataUpdate {
         provider_file_id: Option<String>,
         file_upload_provider: Option<common_enums::FileUploadProvider>,
         available: bool,
-        connector_label: Option<String>,
+        profile_id: Option<String>,
+        merchant_connector_id: Option<String>,
     },
 }
 
@@ -54,7 +57,8 @@ pub struct FileMetadataUpdateInternal {
     provider_file_id: Option<String>,
     file_upload_provider: Option<common_enums::FileUploadProvider>,
     available: bool,
-    connector_label: Option<String>,
+    profile_id: Option<String>,
+    merchant_connector_id: Option<String>,
 }
 
 impl From<FileMetadataUpdate> for FileMetadataUpdateInternal {
@@ -64,12 +68,14 @@ impl From<FileMetadataUpdate> for FileMetadataUpdateInternal {
                 provider_file_id,
                 file_upload_provider,
                 available,
-                connector_label,
+                profile_id,
+                merchant_connector_id,
             } => Self {
                 provider_file_id,
                 file_upload_provider,
                 available,
-                connector_label,
+                profile_id,
+                merchant_connector_id,
             },
         }
     }
diff --git a/crates/diesel_models/src/gsm.rs b/crates/diesel_models/src/gsm.rs
new file mode 100644
index 000000000000..2e824758aa5a
--- /dev/null
+++ b/crates/diesel_models/src/gsm.rs
@@ -0,0 +1,106 @@
+//! Gateway status mapping
+
+use common_utils::{
+    custom_serde,
+    events::{ApiEventMetric, ApiEventsType},
+};
+use diesel::{AsChangeset, Identifiable, Insertable, Queryable};
+use time::PrimitiveDateTime;
+
+use crate::schema::gateway_status_map;
+
+#[derive(
+    Clone,
+    Debug,
+    Eq,
+    PartialEq,
+    router_derive::DebugAsDisplay,
+    Identifiable,
+    Queryable,
+    serde::Serialize,
+)]
+#[diesel(table_name = gateway_status_map, primary_key(connector, flow, sub_flow, code, message))]
+pub struct GatewayStatusMap {
+    pub connector: String,
+    pub flow: String,
+    pub sub_flow: String,
+    pub code: String,
+    pub message: String,
+    pub status: String,
+    pub router_error: Option<String>,
+    pub decision: String,
+    #[serde(with = "custom_serde::iso8601")]
+    pub created_at: PrimitiveDateTime,
+    #[serde(with = "custom_serde::iso8601")]
+    pub last_modified: PrimitiveDateTime,
+    pub step_up_possible: bool,
+}
+
+#[derive(Clone, Debug, Eq, PartialEq, Insertable)]
+#[diesel(table_name = gateway_status_map)]
+pub struct GatewayStatusMappingNew {
+    pub connector: String,
+    pub flow: String,
+    pub sub_flow: String,
+    pub code: String,
+    pub message: String,
+    pub status: String,
+    pub router_error: Option<String>,
+    pub decision: String,
+    pub step_up_possible: bool,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    PartialEq,
+    Eq,
+    AsChangeset,
+    router_derive::DebugAsDisplay,
+    Default,
+    serde::Deserialize,
+)]
+#[diesel(table_name = gateway_status_map)]
+pub struct GatewayStatusMapperUpdateInternal {
+    pub connector: Option<String>,
+    pub flow: Option<String>,
+    pub sub_flow: Option<String>,
+    pub code: Option<String>,
+    pub message: Option<String>,
+    pub status: Option<String>,
+    pub router_error: Option<Option<String>>,
+    pub decision: Option<String>,
+    pub step_up_possible: Option<bool>,
+}
+
+#[derive(Debug)]
+pub struct GatewayStatusMappingUpdate {
+    pub status: Option<String>,
+    pub router_error: Option<Option<String>>,
+    pub decision: Option<String>,
+    pub step_up_possible: Option<bool>,
+}
+
+impl From<GatewayStatusMappingUpdate> for GatewayStatusMapperUpdateInternal {
+    fn from(value: GatewayStatusMappingUpdate) -> Self {
+        let GatewayStatusMappingUpdate {
+            decision,
+            status,
+            router_error,
+            step_up_possible,
+        } = value;
+        Self {
+            status,
+            router_error,
+            decision,
+            step_up_possible,
+            ..Default::default()
+        }
+    }
+}
+
+impl ApiEventMetric for GatewayStatusMap {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        Some(ApiEventsType::Gsm)
+    }
+}
diff --git a/crates/diesel_models/src/kv.rs b/crates/diesel_models/src/kv.rs
index f1145a4b6e1f..f56ef8304186 100644
--- a/crates/diesel_models/src/kv.rs
+++ b/crates/diesel_models/src/kv.rs
@@ -3,7 +3,6 @@ use serde::{Deserialize, Serialize};
 
 use crate::{
     address::{Address, AddressNew, AddressUpdateInternal},
-    connector_response::{ConnectorResponse, ConnectorResponseNew, ConnectorResponseUpdate},
     errors,
     payment_attempt::{PaymentAttempt, PaymentAttemptNew, PaymentAttemptUpdate},
     payment_intent::{PaymentIntentNew, PaymentIntentUpdate},
@@ -27,13 +26,21 @@ pub struct TypedSql {
 }
 
 impl TypedSql {
-    pub fn to_field_value_pairs(&self) -> crate::StorageResult<Vec<(&str, String)>> {
-        Ok(vec![(
-            "typed_sql",
-            serde_json::to_string(self)
-                .into_report()
-                .change_context(errors::DatabaseError::QueryGenerationFailed)?,
-        )])
+    pub fn to_field_value_pairs(
+        &self,
+        request_id: String,
+        global_id: String,
+    ) -> crate::StorageResult<Vec<(&str, String)>> {
+        Ok(vec![
+            (
+                "typed_sql",
+                serde_json::to_string(self)
+                    .into_report()
+                    .change_context(errors::DatabaseError::QueryGenerationFailed)?,
+            ),
+            ("global_id", global_id),
+            ("request_id", request_id),
+        ])
     }
 }
 
@@ -43,7 +50,6 @@ pub enum Insertable {
     PaymentIntent(PaymentIntentNew),
     PaymentAttempt(PaymentAttemptNew),
     Refund(RefundNew),
-    ConnectorResponse(ConnectorResponseNew),
     Address(Box<AddressNew>),
     ReverseLookUp(ReverseLookupNew),
 }
@@ -54,16 +60,9 @@ pub enum Updateable {
     PaymentIntentUpdate(PaymentIntentUpdateMems),
     PaymentAttemptUpdate(PaymentAttemptUpdateMems),
     RefundUpdate(RefundUpdateMems),
-    ConnectorResponseUpdate(ConnectorResponseUpdateMems),
     AddressUpdate(Box<AddressUpdateMems>),
 }
 
-#[derive(Debug, Serialize, Deserialize)]
-pub struct ConnectorResponseUpdateMems {
-    pub orig: ConnectorResponse,
-    pub update_data: ConnectorResponseUpdate,
-}
-
 #[derive(Debug, Serialize, Deserialize)]
 pub struct AddressUpdateMems {
     pub orig: Address,
diff --git a/crates/diesel_models/src/lib.rs b/crates/diesel_models/src/lib.rs
index 3de35d73f822..781099662a50 100644
--- a/crates/diesel_models/src/lib.rs
+++ b/crates/diesel_models/src/lib.rs
@@ -4,7 +4,7 @@ pub mod business_profile;
 pub mod capture;
 pub mod cards_info;
 pub mod configs;
-pub mod connector_response;
+
 pub mod customers;
 pub mod dispute;
 pub mod encryption;
@@ -15,6 +15,7 @@ pub mod events;
 pub mod file;
 #[allow(unused)]
 pub mod fraud_check;
+pub mod gsm;
 #[cfg(feature = "kv_store")]
 pub mod kv;
 pub mod locker_mock_up;
@@ -23,6 +24,7 @@ pub mod mandate;
 pub mod merchant_account;
 pub mod merchant_connector_account;
 pub mod merchant_key_store;
+pub mod organization;
 pub mod payment_attempt;
 pub mod payment_intent;
 pub mod payment_link;
@@ -33,18 +35,21 @@ pub mod process_tracker;
 pub mod query;
 pub mod refund;
 pub mod reverse_lookup;
+pub mod routing_algorithm;
 #[allow(unused_qualifications)]
 pub mod schema;
+pub mod user;
+pub mod user_role;
 
 use diesel_impl::{DieselArray, OptionalDieselArray};
 
 pub type StorageResult<T> = error_stack::Result<T, errors::DatabaseError>;
 pub type PgPooledConn = async_bb8_diesel::Connection<diesel::PgConnection>;
 pub use self::{
-    address::*, api_keys::*, cards_info::*, configs::*, connector_response::*, customers::*,
-    dispute::*, ephemeral_key::*, events::*, file::*, locker_mock_up::*, mandate::*,
-    merchant_account::*, merchant_connector_account::*, payment_attempt::*, payment_intent::*,
-    payment_method::*, process_tracker::*, refund::*, reverse_lookup::*,
+    address::*, api_keys::*, cards_info::*, configs::*, customers::*, dispute::*, ephemeral_key::*,
+    events::*, file::*, locker_mock_up::*, mandate::*, merchant_account::*,
+    merchant_connector_account::*, payment_attempt::*, payment_intent::*, payment_method::*,
+    process_tracker::*, refund::*, reverse_lookup::*,
 };
 
 /// The types and implementations provided by this module are required for the schema generated by
diff --git a/crates/diesel_models/src/mandate.rs b/crates/diesel_models/src/mandate.rs
index 0b7f3db51a59..cc3474914c01 100644
--- a/crates/diesel_models/src/mandate.rs
+++ b/crates/diesel_models/src/mandate.rs
@@ -31,6 +31,7 @@ pub struct Mandate {
     pub metadata: Option<pii::SecretSerdeValue>,
     pub connector_mandate_ids: Option<pii::SecretSerdeValue>,
     pub original_payment_id: Option<String>,
+    pub merchant_connector_id: Option<String>,
 }
 
 #[derive(
@@ -60,6 +61,7 @@ pub struct MandateNew {
     pub metadata: Option<pii::SecretSerdeValue>,
     pub connector_mandate_ids: Option<pii::SecretSerdeValue>,
     pub original_payment_id: Option<String>,
+    pub merchant_connector_id: Option<String>,
 }
 
 #[derive(Debug)]
diff --git a/crates/diesel_models/src/organization.rs b/crates/diesel_models/src/organization.rs
new file mode 100644
index 000000000000..2f407b8cbfdd
--- /dev/null
+++ b/crates/diesel_models/src/organization.rs
@@ -0,0 +1,35 @@
+use diesel::{AsChangeset, Identifiable, Insertable, Queryable};
+
+use crate::schema::organization;
+
+#[derive(Clone, Debug, Identifiable, Queryable)]
+#[diesel(table_name = organization, primary_key(org_id))]
+pub struct Organization {
+    pub org_id: String,
+    pub org_name: Option<String>,
+}
+
+#[derive(Clone, Debug, Insertable)]
+#[diesel(table_name = organization, primary_key(org_id))]
+pub struct OrganizationNew {
+    pub org_id: String,
+    pub org_name: Option<String>,
+}
+
+#[derive(Clone, Debug, AsChangeset)]
+#[diesel(table_name = organization)]
+pub struct OrganizationUpdateInternal {
+    org_name: Option<String>,
+}
+
+pub enum OrganizationUpdate {
+    Update { org_name: Option<String> },
+}
+
+impl From<OrganizationUpdate> for OrganizationUpdateInternal {
+    fn from(value: OrganizationUpdate) -> Self {
+        match value {
+            OrganizationUpdate::Update { org_name } => Self { org_name },
+        }
+    }
+}
diff --git a/crates/diesel_models/src/payment_attempt.rs b/crates/diesel_models/src/payment_attempt.rs
index cf6815439289..cd976b9e19db 100644
--- a/crates/diesel_models/src/payment_attempt.rs
+++ b/crates/diesel_models/src/payment_attempt.rs
@@ -57,8 +57,10 @@ pub struct PaymentAttempt {
     // reference to the payment at connector side
     pub connector_response_reference_id: Option<String>,
     pub amount_capturable: i64,
-    pub surcharge_metadata: Option<serde_json::Value>,
     pub updated_by: String,
+    pub merchant_connector_id: Option<String>,
+    pub authentication_data: Option<serde_json::Value>,
+    pub encoded_data: Option<String>,
 }
 
 #[derive(Clone, Debug, Eq, PartialEq, Queryable, Serialize, Deserialize)]
@@ -68,6 +70,7 @@ pub struct PaymentListFilters {
     pub status: Vec<storage_enums::IntentStatus>,
     pub payment_method: Vec<storage_enums::PaymentMethod>,
 }
+
 #[derive(
     Clone, Debug, Default, Insertable, router_derive::DebugAsDisplay, Serialize, Deserialize,
 )]
@@ -117,8 +120,10 @@ pub struct PaymentAttemptNew {
     pub connector_response_reference_id: Option<String>,
     pub multiple_capture_count: Option<i16>,
     pub amount_capturable: i64,
-    pub surcharge_metadata: Option<serde_json::Value>,
     pub updated_by: String,
+    pub merchant_connector_id: Option<String>,
+    pub authentication_data: Option<serde_json::Value>,
+    pub encoded_data: Option<String>,
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -136,6 +141,8 @@ pub enum PaymentAttemptUpdate {
         business_sub_label: Option<String>,
         amount_to_capture: Option<i64>,
         capture_method: Option<storage_enums::CaptureMethod>,
+        surcharge_amount: Option<i64>,
+        tax_amount: Option<i64>,
         updated_by: String,
     },
     UpdateTrackers {
@@ -143,7 +150,10 @@ pub enum PaymentAttemptUpdate {
         connector: Option<String>,
         straight_through_algorithm: Option<serde_json::Value>,
         amount_capturable: Option<i64>,
+        surcharge_amount: Option<i64>,
+        tax_amount: Option<i64>,
         updated_by: String,
+        merchant_connector_id: Option<String>,
     },
     AuthenticationTypeUpdate {
         authentication_type: storage_enums::AuthenticationType,
@@ -166,9 +176,8 @@ pub enum PaymentAttemptUpdate {
         error_code: Option<Option<String>>,
         error_message: Option<Option<String>>,
         amount_capturable: Option<i64>,
-        surcharge_amount: Option<i64>,
-        tax_amount: Option<i64>,
         updated_by: String,
+        merchant_connector_id: Option<String>,
     },
     VoidUpdate {
         status: storage_enums::AttemptStatus,
@@ -195,7 +204,11 @@ pub enum PaymentAttemptUpdate {
         error_reason: Option<Option<String>>,
         connector_response_reference_id: Option<String>,
         amount_capturable: Option<i64>,
+        surcharge_amount: Option<i64>,
+        tax_amount: Option<i64>,
         updated_by: String,
+        authentication_data: Option<serde_json::Value>,
+        encoded_data: Option<String>,
     },
     UnresolvedResponseUpdate {
         status: storage_enums::AttemptStatus,
@@ -239,8 +252,11 @@ pub enum PaymentAttemptUpdate {
         connector_response_reference_id: Option<String>,
         updated_by: String,
     },
-    SurchargeMetadataUpdate {
-        surcharge_metadata: Option<serde_json::Value>,
+    ConnectorResponse {
+        authentication_data: Option<serde_json::Value>,
+        encoded_data: Option<String>,
+        connector_transaction_id: Option<String>,
+        connector: Option<String>,
         updated_by: String,
     },
 }
@@ -278,8 +294,10 @@ pub struct PaymentAttemptUpdateInternal {
     surcharge_amount: Option<i64>,
     tax_amount: Option<i64>,
     amount_capturable: Option<i64>,
-    surcharge_metadata: Option<serde_json::Value>,
     updated_by: String,
+    merchant_connector_id: Option<String>,
+    authentication_data: Option<serde_json::Value>,
+    encoded_data: Option<String>,
 }
 
 impl PaymentAttemptUpdate {
@@ -330,8 +348,10 @@ impl PaymentAttemptUpdate {
             amount_capturable: pa_update
                 .amount_capturable
                 .unwrap_or(source.amount_capturable),
-            surcharge_metadata: pa_update.surcharge_metadata.or(source.surcharge_metadata),
             updated_by: pa_update.updated_by,
+            merchant_connector_id: pa_update.merchant_connector_id,
+            authentication_data: pa_update.authentication_data.or(source.authentication_data),
+            encoded_data: pa_update.encoded_data.or(source.encoded_data),
             ..source
         }
     }
@@ -354,6 +374,8 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 business_sub_label,
                 amount_to_capture,
                 capture_method,
+                surcharge_amount,
+                tax_amount,
                 updated_by,
             } => Self {
                 amount: Some(amount),
@@ -370,6 +392,8 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 business_sub_label,
                 amount_to_capture,
                 capture_method,
+                surcharge_amount,
+                tax_amount,
                 updated_by,
                 ..Default::default()
             },
@@ -399,9 +423,8 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 error_code,
                 error_message,
                 amount_capturable,
-                surcharge_amount,
-                tax_amount,
                 updated_by,
+                merchant_connector_id,
             } => Self {
                 amount: Some(amount),
                 currency: Some(currency),
@@ -420,9 +443,8 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 error_code,
                 error_message,
                 amount_capturable,
-                surcharge_amount,
-                tax_amount,
                 updated_by,
+                merchant_connector_id,
                 ..Default::default()
             },
             PaymentAttemptUpdate::VoidUpdate {
@@ -461,7 +483,11 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 error_reason,
                 connector_response_reference_id,
                 amount_capturable,
+                surcharge_amount,
+                tax_amount,
                 updated_by,
+                authentication_data,
+                encoded_data,
             } => Self {
                 status: Some(status),
                 connector,
@@ -478,6 +504,10 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 connector_response_reference_id,
                 amount_capturable,
                 updated_by,
+                surcharge_amount,
+                tax_amount,
+                authentication_data,
+                encoded_data,
                 ..Default::default()
             },
             PaymentAttemptUpdate::ErrorUpdate {
@@ -509,13 +539,19 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 connector,
                 straight_through_algorithm,
                 amount_capturable,
+                surcharge_amount,
+                tax_amount,
                 updated_by,
+                merchant_connector_id,
             } => Self {
                 payment_token,
                 connector,
                 straight_through_algorithm,
                 amount_capturable,
+                surcharge_amount,
+                tax_amount,
                 updated_by,
+                merchant_connector_id,
                 ..Default::default()
             },
             PaymentAttemptUpdate::UnresolvedResponseUpdate {
@@ -578,11 +614,17 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 updated_by,
                 ..Default::default()
             },
-            PaymentAttemptUpdate::SurchargeMetadataUpdate {
-                surcharge_metadata,
+            PaymentAttemptUpdate::ConnectorResponse {
+                authentication_data,
+                encoded_data,
+                connector_transaction_id,
+                connector,
                 updated_by,
             } => Self {
-                surcharge_metadata,
+                authentication_data,
+                encoded_data,
+                connector_transaction_id,
+                connector,
                 updated_by,
                 ..Default::default()
             },
diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs
index f449cadbba59..2ffa857026ba 100644
--- a/crates/diesel_models/src/payment_intent.rs
+++ b/crates/diesel_models/src/payment_intent.rs
@@ -48,7 +48,9 @@ pub struct PaymentIntent {
     pub merchant_decision: Option<String>,
     pub payment_link_id: Option<String>,
     pub payment_confirm_source: Option<storage_enums::PaymentSource>,
+
     pub updated_by: String,
+    pub surcharge_applicable: Option<bool>,
 }
 
 #[derive(
@@ -101,7 +103,9 @@ pub struct PaymentIntentNew {
     pub merchant_decision: Option<String>,
     pub payment_link_id: Option<String>,
     pub payment_confirm_source: Option<storage_enums::PaymentSource>,
+
     pub updated_by: String,
+    pub surcharge_applicable: Option<bool>,
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -173,6 +177,10 @@ pub enum PaymentIntentUpdate {
         merchant_decision: Option<String>,
         updated_by: String,
     },
+    SurchargeApplicableUpdate {
+        surcharge_applicable: Option<bool>,
+        updated_by: String,
+    },
 }
 
 #[derive(Clone, Debug, Default, AsChangeset, router_derive::DebugAsDisplay)]
@@ -202,7 +210,9 @@ pub struct PaymentIntentUpdateInternal {
     pub profile_id: Option<String>,
     merchant_decision: Option<String>,
     payment_confirm_source: Option<storage_enums::PaymentSource>,
+
     pub updated_by: String,
+    pub surcharge_applicable: Option<bool>,
 }
 
 impl PaymentIntentUpdate {
@@ -402,6 +412,14 @@ impl From<PaymentIntentUpdate> for PaymentIntentUpdateInternal {
                 updated_by,
                 ..Default::default()
             },
+            PaymentIntentUpdate::SurchargeApplicableUpdate {
+                surcharge_applicable,
+                updated_by,
+            } => Self {
+                surcharge_applicable,
+                updated_by,
+                ..Default::default()
+            },
         }
     }
 }
diff --git a/crates/diesel_models/src/payment_link.rs b/crates/diesel_models/src/payment_link.rs
index 4b182a8155a5..50cc5e89cee9 100644
--- a/crates/diesel_models/src/payment_link.rs
+++ b/crates/diesel_models/src/payment_link.rs
@@ -20,8 +20,8 @@ pub struct PaymentLink {
     pub last_modified_at: PrimitiveDateTime,
     #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
     pub fulfilment_time: Option<PrimitiveDateTime>,
+    pub custom_merchant_name: Option<String>,
 }
-
 #[derive(
     Clone,
     Debug,
@@ -47,4 +47,5 @@ pub struct PaymentLinkNew {
     pub last_modified_at: Option<PrimitiveDateTime>,
     #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
     pub fulfilment_time: Option<PrimitiveDateTime>,
+    pub custom_merchant_name: Option<String>,
 }
diff --git a/crates/diesel_models/src/payout_attempt.rs b/crates/diesel_models/src/payout_attempt.rs
index 64ba10551153..d87ed5319a91 100644
--- a/crates/diesel_models/src/payout_attempt.rs
+++ b/crates/diesel_models/src/payout_attempt.rs
@@ -27,6 +27,7 @@ pub struct PayoutAttempt {
     #[serde(with = "common_utils::custom_serde::iso8601")]
     pub last_modified_at: PrimitiveDateTime,
     pub profile_id: Option<String>,
+    pub merchant_connector_id: Option<String>,
 }
 
 impl Default for PayoutAttempt {
@@ -51,6 +52,7 @@ impl Default for PayoutAttempt {
             created_at: now,
             last_modified_at: now,
             profile_id: None,
+            merchant_connector_id: None,
         }
     }
 }
@@ -88,6 +90,7 @@ pub struct PayoutAttemptNew {
     #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
     pub last_modified_at: Option<PrimitiveDateTime>,
     pub profile_id: Option<String>,
+    pub merchant_connector_id: Option<String>,
 }
 
 #[derive(Debug)]
diff --git a/crates/diesel_models/src/query.rs b/crates/diesel_models/src/query.rs
index ef4ab9f32fa3..cf5a993c2686 100644
--- a/crates/diesel_models/src/query.rs
+++ b/crates/diesel_models/src/query.rs
@@ -4,18 +4,20 @@ pub mod business_profile;
 mod capture;
 pub mod cards_info;
 pub mod configs;
-pub mod connector_response;
+
 pub mod customers;
 pub mod dispute;
 pub mod events;
 pub mod file;
 pub mod fraud_check;
 pub mod generics;
+pub mod gsm;
 pub mod locker_mock_up;
 pub mod mandate;
 pub mod merchant_account;
 pub mod merchant_connector_account;
 pub mod merchant_key_store;
+pub mod organization;
 pub mod payment_attempt;
 pub mod payment_intent;
 pub mod payment_link;
@@ -25,3 +27,6 @@ pub mod payouts;
 pub mod process_tracker;
 pub mod refund;
 pub mod reverse_lookup;
+pub mod routing_algorithm;
+pub mod user;
+pub mod user_role;
diff --git a/crates/diesel_models/src/query/connector_response.rs b/crates/diesel_models/src/query/connector_response.rs
index eea7e779d8d5..952db945ae38 100644
--- a/crates/diesel_models/src/query/connector_response.rs
+++ b/crates/diesel_models/src/query/connector_response.rs
@@ -1,5 +1,5 @@
 use diesel::{associations::HasTable, BoolExpressionMethods, ExpressionMethods};
-use router_env::{instrument, tracing};
+use router_env::{instrument, logger, tracing};
 
 use super::generics;
 use crate::{
@@ -8,13 +8,44 @@ use crate::{
         ConnectorResponseUpdateInternal,
     },
     errors,
-    schema::connector_response::dsl,
+    payment_attempt::{PaymentAttempt, PaymentAttemptUpdate, PaymentAttemptUpdateInternal},
+    schema::{connector_response::dsl, payment_attempt::dsl as pa_dsl},
     PgPooledConn, StorageResult,
 };
 
 impl ConnectorResponseNew {
     #[instrument(skip(conn))]
     pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<ConnectorResponse> {
+        let payment_attempt_update = PaymentAttemptUpdate::ConnectorResponse {
+            authentication_data: self.authentication_data.clone(),
+            encoded_data: self.encoded_data.clone(),
+            connector_transaction_id: self.connector_transaction_id.clone(),
+            connector: self.connector_name.clone(),
+            updated_by: self.updated_by.clone(),
+        };
+
+        let _payment_attempt: Result<PaymentAttempt, _> =
+            generics::generic_update_with_unique_predicate_get_result::<
+                <PaymentAttempt as HasTable>::Table,
+                _,
+                _,
+                _,
+            >(
+                conn,
+                pa_dsl::attempt_id
+                    .eq(self.attempt_id.to_owned())
+                    .and(pa_dsl::merchant_id.eq(self.merchant_id.to_owned())),
+                PaymentAttemptUpdateInternal::from(payment_attempt_update),
+            )
+            .await
+            .map_err(|err| {
+                logger::error!(
+                    "Error while updating payment attempt in connector_response flow {:?}",
+                    err
+                );
+                err
+            });
+
         generics::generic_insert(conn, self).await
     }
 }
@@ -26,27 +57,78 @@ impl ConnectorResponse {
         conn: &PgPooledConn,
         connector_response: ConnectorResponseUpdate,
     ) -> StorageResult<Self> {
-        match generics::generic_update_with_unique_predicate_get_result::<
-            <Self as HasTable>::Table,
-            _,
-            _,
-            _,
-        >(
-            conn,
-            dsl::merchant_id
-                .eq(self.merchant_id.clone())
-                .and(dsl::payment_id.eq(self.payment_id.clone()))
-                .and(dsl::attempt_id.eq(self.attempt_id.clone())),
-            ConnectorResponseUpdateInternal::from(connector_response),
-        )
-        .await
-        {
-            Err(error) => match error.current_context() {
-                errors::DatabaseError::NoFieldsToUpdate => Ok(self),
-                _ => Err(error),
+        let payment_attempt_update = match connector_response.clone() {
+            ConnectorResponseUpdate::ResponseUpdate {
+                connector_transaction_id,
+                authentication_data,
+                encoded_data,
+                connector_name,
+                updated_by,
+            } => PaymentAttemptUpdate::ConnectorResponse {
+                authentication_data,
+                encoded_data,
+                connector_transaction_id,
+                connector: connector_name,
+                updated_by,
             },
-            result => result,
-        }
+            ConnectorResponseUpdate::ErrorUpdate {
+                connector_name,
+                updated_by,
+            } => PaymentAttemptUpdate::ConnectorResponse {
+                authentication_data: None,
+                encoded_data: None,
+                connector_transaction_id: None,
+                connector: connector_name,
+                updated_by,
+            },
+        };
+
+        let _payment_attempt: Result<PaymentAttempt, _> =
+            generics::generic_update_with_unique_predicate_get_result::<
+                <PaymentAttempt as HasTable>::Table,
+                _,
+                _,
+                _,
+            >(
+                conn,
+                pa_dsl::attempt_id
+                    .eq(self.attempt_id.to_owned())
+                    .and(pa_dsl::merchant_id.eq(self.merchant_id.to_owned())),
+                PaymentAttemptUpdateInternal::from(payment_attempt_update),
+            )
+            .await
+            .map_err(|err| {
+                logger::error!(
+                    "Error while updating payment attempt in connector_response flow {:?}",
+                    err
+                );
+                err
+            });
+
+        let connector_response_result =
+            match generics::generic_update_with_unique_predicate_get_result::<
+                <Self as HasTable>::Table,
+                _,
+                _,
+                _,
+            >(
+                conn,
+                dsl::merchant_id
+                    .eq(self.merchant_id.clone())
+                    .and(dsl::payment_id.eq(self.payment_id.clone()))
+                    .and(dsl::attempt_id.eq(self.attempt_id.clone())),
+                ConnectorResponseUpdateInternal::from(connector_response),
+            )
+            .await
+            {
+                Err(error) => match error.current_context() {
+                    errors::DatabaseError::NoFieldsToUpdate => Ok(self),
+                    _ => Err(error),
+                },
+                result => result,
+            };
+
+        connector_response_result
     }
 
     #[instrument(skip(conn))]
@@ -56,14 +138,69 @@ impl ConnectorResponse {
         merchant_id: &str,
         attempt_id: &str,
     ) -> StorageResult<Self> {
-        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
+        let connector_response: Self =
+            generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
+                conn,
+                dsl::merchant_id.eq(merchant_id.to_owned()).and(
+                    dsl::payment_id
+                        .eq(payment_id.to_owned())
+                        .and(dsl::attempt_id.eq(attempt_id.to_owned())),
+                ),
+            )
+            .await?;
+
+        match generics::generic_find_one::<<PaymentAttempt as HasTable>::Table, _, _>(
             conn,
-            dsl::merchant_id.eq(merchant_id.to_owned()).and(
-                dsl::payment_id
-                    .eq(payment_id.to_owned())
-                    .and(dsl::attempt_id.eq(attempt_id.to_owned())),
+            pa_dsl::payment_id.eq(payment_id.to_owned()).and(
+                pa_dsl::merchant_id
+                    .eq(merchant_id.to_owned())
+                    .and(pa_dsl::attempt_id.eq(attempt_id.to_owned())),
             ),
         )
         .await
+        {
+            Ok::<PaymentAttempt, _>(payment_attempt) => {
+                if payment_attempt.authentication_data != connector_response.authentication_data {
+                    logger::error!(
+                        "Not Equal pa_authentication_data : {:?}, cr_authentication_data: {:?} ",
+                        payment_attempt.authentication_data,
+                        connector_response.authentication_data
+                    );
+                }
+
+                if payment_attempt.encoded_data != connector_response.encoded_data {
+                    logger::error!(
+                        "Not Equal pa_encoded_data : {:?}, cr_encoded_data: {:?} ",
+                        payment_attempt.encoded_data,
+                        connector_response.encoded_data
+                    );
+                }
+
+                if payment_attempt.connector_transaction_id
+                    != connector_response.connector_transaction_id
+                {
+                    logger::error!(
+                            "Not Equal pa_connector_transaction_id : {:?}, cr_connector_transaction_id: {:?} ",
+                            payment_attempt.connector_transaction_id,
+                            connector_response.connector_transaction_id
+                        );
+                }
+                if payment_attempt.connector != connector_response.connector_name {
+                    logger::error!(
+                        "Not Equal pa_connector : {:?}, cr_connector_name: {:?} ",
+                        payment_attempt.connector,
+                        connector_response.connector_name
+                    );
+                }
+            }
+            Err(err) => {
+                logger::error!(
+                    "Error while finding payment attempt in connector_response flow {:?}",
+                    err
+                );
+            }
+        }
+
+        Ok(connector_response)
     }
 }
diff --git a/crates/diesel_models/src/query/gsm.rs b/crates/diesel_models/src/query/gsm.rs
new file mode 100644
index 000000000000..bd44ce4dc378
--- /dev/null
+++ b/crates/diesel_models/src/query/gsm.rs
@@ -0,0 +1,100 @@
+use diesel::{associations::HasTable, BoolExpressionMethods, ExpressionMethods};
+use error_stack::report;
+
+use crate::{
+    errors, gsm::*, query::generics, schema::gateway_status_map::dsl, PgPooledConn, StorageResult,
+};
+
+impl GatewayStatusMappingNew {
+    pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<GatewayStatusMap> {
+        generics::generic_insert(conn, self).await
+    }
+}
+
+impl GatewayStatusMap {
+    pub async fn find(
+        conn: &PgPooledConn,
+        connector: String,
+        flow: String,
+        sub_flow: String,
+        code: String,
+        message: String,
+    ) -> StorageResult<Self> {
+        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
+            conn,
+            dsl::connector
+                .eq(connector)
+                .and(dsl::flow.eq(flow))
+                .and(dsl::sub_flow.eq(sub_flow))
+                .and(dsl::code.eq(code))
+                .and(dsl::message.eq(message)),
+        )
+        .await
+    }
+
+    pub async fn retrieve_decision(
+        conn: &PgPooledConn,
+        connector: String,
+        flow: String,
+        sub_flow: String,
+        code: String,
+        message: String,
+    ) -> StorageResult<String> {
+        Self::find(conn, connector, flow, sub_flow, code, message)
+            .await
+            .map(|item| item.decision)
+    }
+
+    pub async fn update(
+        conn: &PgPooledConn,
+        connector: String,
+        flow: String,
+        sub_flow: String,
+        code: String,
+        message: String,
+        gsm: GatewayStatusMappingUpdate,
+    ) -> StorageResult<Self> {
+        generics::generic_update_with_results::<
+            <Self as HasTable>::Table,
+            GatewayStatusMapperUpdateInternal,
+            _,
+            _,
+        >(
+            conn,
+            dsl::connector
+                .eq(connector)
+                .and(dsl::flow.eq(flow))
+                .and(dsl::sub_flow.eq(sub_flow))
+                .and(dsl::code.eq(code))
+                .and(dsl::message.eq(message)),
+            gsm.into(),
+        )
+        .await?
+        .first()
+        .cloned()
+        .ok_or_else(|| {
+            report!(errors::DatabaseError::NotFound)
+                .attach_printable("Error while updating gsm entry")
+        })
+    }
+
+    pub async fn delete(
+        conn: &PgPooledConn,
+        connector: String,
+        flow: String,
+        sub_flow: String,
+        code: String,
+        message: String,
+    ) -> StorageResult<bool> {
+        generics::generic_delete::<<Self as HasTable>::Table, _>(
+            conn,
+            dsl::connector
+                .eq(connector)
+                .and(dsl::flow.eq(flow))
+                .and(dsl::sub_flow.eq(sub_flow))
+                .and(dsl::code.eq(code))
+                .and(dsl::message.eq(message)),
+        )
+        .await
+    }
+}
diff --git a/crates/diesel_models/src/query/merchant_connector_account.rs b/crates/diesel_models/src/query/merchant_connector_account.rs
index 17e34b2a866d..e9ef4eabff0e 100644
--- a/crates/diesel_models/src/query/merchant_connector_account.rs
+++ b/crates/diesel_models/src/query/merchant_connector_account.rs
@@ -130,17 +130,12 @@ impl MerchantConnectorAccount {
         get_disabled: bool,
     ) -> StorageResult<Vec<Self>> {
         if get_disabled {
-            generics::generic_filter::<
-                <Self as HasTable>::Table,
-                _,
-                <<Self as HasTable>::Table as Table>::PrimaryKey,
-                _,
-            >(
+            generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
                 conn,
                 dsl::merchant_id.eq(merchant_id.to_owned()),
                 None,
                 None,
-                None,
+                Some(dsl::created_at.asc()),
             )
             .await
         } else {
diff --git a/crates/diesel_models/src/query/organization.rs b/crates/diesel_models/src/query/organization.rs
new file mode 100644
index 000000000000..0bea1012c9a9
--- /dev/null
+++ b/crates/diesel_models/src/query/organization.rs
@@ -0,0 +1,38 @@
+use diesel::{associations::HasTable, ExpressionMethods};
+use router_env::tracing::{self, instrument};
+
+use crate::{
+    organization::*, query::generics, schema::organization::dsl, PgPooledConn, StorageResult,
+};
+
+impl OrganizationNew {
+    #[instrument(skip(conn))]
+    pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<Organization> {
+        generics::generic_insert(conn, self).await
+    }
+}
+
+impl Organization {
+    pub async fn find_by_org_id(conn: &PgPooledConn, org_id: String) -> StorageResult<Self> {
+        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(conn, dsl::org_id.eq(org_id))
+            .await
+    }
+
+    pub async fn update_by_org_id(
+        conn: &PgPooledConn,
+        org_id: String,
+        update: OrganizationUpdate,
+    ) -> StorageResult<Self> {
+        generics::generic_update_with_unique_predicate_get_result::<
+            <Self as HasTable>::Table,
+            _,
+            _,
+            _,
+        >(
+            conn,
+            dsl::org_id.eq(org_id),
+            OrganizationUpdateInternal::from(update),
+        )
+        .await
+    }
+}
diff --git a/crates/diesel_models/src/query/routing_algorithm.rs b/crates/diesel_models/src/query/routing_algorithm.rs
new file mode 100644
index 000000000000..533ac7194c41
--- /dev/null
+++ b/crates/diesel_models/src/query/routing_algorithm.rs
@@ -0,0 +1,200 @@
+use async_bb8_diesel::AsyncRunQueryDsl;
+use diesel::{associations::HasTable, BoolExpressionMethods, ExpressionMethods, QueryDsl};
+use error_stack::{IntoReport, ResultExt};
+use router_env::tracing::{self, instrument};
+use time::PrimitiveDateTime;
+
+use crate::{
+    enums,
+    errors::DatabaseError,
+    query::generics,
+    routing_algorithm::{RoutingAlgorithm, RoutingAlgorithmMetadata, RoutingProfileMetadata},
+    schema::routing_algorithm::dsl,
+    PgPooledConn, StorageResult,
+};
+
+impl RoutingAlgorithm {
+    #[instrument(skip(conn))]
+    pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<Self> {
+        generics::generic_insert(conn, self).await
+    }
+
+    #[instrument(skip(conn))]
+    pub async fn find_by_algorithm_id_merchant_id(
+        conn: &PgPooledConn,
+        algorithm_id: &str,
+        merchant_id: &str,
+    ) -> StorageResult<Self> {
+        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
+            conn,
+            dsl::algorithm_id
+                .eq(algorithm_id.to_owned())
+                .and(dsl::merchant_id.eq(merchant_id.to_owned())),
+        )
+        .await
+    }
+
+    #[instrument(skip(conn))]
+    pub async fn find_by_algorithm_id_profile_id(
+        conn: &PgPooledConn,
+        algorithm_id: &str,
+        profile_id: &str,
+    ) -> StorageResult<Self> {
+        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
+            conn,
+            dsl::algorithm_id
+                .eq(algorithm_id.to_owned())
+                .and(dsl::profile_id.eq(profile_id.to_owned())),
+        )
+        .await
+    }
+
+    #[instrument(skip(conn))]
+    pub async fn find_metadata_by_algorithm_id_profile_id(
+        conn: &PgPooledConn,
+        algorithm_id: &str,
+        profile_id: &str,
+    ) -> StorageResult<RoutingProfileMetadata> {
+        Self::table()
+            .select((
+                dsl::profile_id,
+                dsl::algorithm_id,
+                dsl::name,
+                dsl::description,
+                dsl::kind,
+                dsl::created_at,
+                dsl::modified_at,
+            ))
+            .filter(
+                dsl::algorithm_id
+                    .eq(algorithm_id.to_owned())
+                    .and(dsl::profile_id.eq(profile_id.to_owned())),
+            )
+            .limit(1)
+            .load_async::<(
+                String,
+                String,
+                String,
+                Option<String>,
+                enums::RoutingAlgorithmKind,
+                PrimitiveDateTime,
+                PrimitiveDateTime,
+            )>(conn)
+            .await
+            .into_report()
+            .change_context(DatabaseError::Others)?
+            .into_iter()
+            .next()
+            .ok_or(DatabaseError::NotFound)
+            .into_report()
+            .map(
+                |(profile_id, algorithm_id, name, description, kind, created_at, modified_at)| {
+                    RoutingProfileMetadata {
+                        profile_id,
+                        algorithm_id,
+                        name,
+                        description,
+                        kind,
+                        created_at,
+                        modified_at,
+                    }
+                },
+            )
+    }
+
+    #[instrument(skip(conn))]
+    pub async fn list_metadata_by_profile_id(
+        conn: &PgPooledConn,
+        profile_id: &str,
+        limit: i64,
+        offset: i64,
+    ) -> StorageResult<Vec<RoutingAlgorithmMetadata>> {
+        Ok(Self::table()
+            .select((
+                dsl::algorithm_id,
+                dsl::name,
+                dsl::description,
+                dsl::kind,
+                dsl::created_at,
+                dsl::modified_at,
+            ))
+            .filter(dsl::profile_id.eq(profile_id.to_owned()))
+            .limit(limit)
+            .offset(offset)
+            .load_async::<(
+                String,
+                String,
+                Option<String>,
+                enums::RoutingAlgorithmKind,
+                PrimitiveDateTime,
+                PrimitiveDateTime,
+            )>(conn)
+            .await
+            .into_report()
+            .change_context(DatabaseError::Others)?
+            .into_iter()
+            .map(
+                |(algorithm_id, name, description, kind, created_at, modified_at)| {
+                    RoutingAlgorithmMetadata {
+                        algorithm_id,
+                        name,
+                        description,
+                        kind,
+                        created_at,
+                        modified_at,
+                    }
+                },
+            )
+            .collect())
+    }
+
+    #[instrument(skip(conn))]
+    pub async fn list_metadata_by_merchant_id(
+        conn: &PgPooledConn,
+        merchant_id: &str,
+        limit: i64,
+        offset: i64,
+    ) -> StorageResult<Vec<RoutingProfileMetadata>> {
+        Ok(Self::table()
+            .select((
+                dsl::profile_id,
+                dsl::algorithm_id,
+                dsl::name,
+                dsl::description,
+                dsl::kind,
+                dsl::created_at,
+                dsl::modified_at,
+            ))
+            .filter(dsl::merchant_id.eq(merchant_id.to_owned()))
+            .limit(limit)
+            .offset(offset)
+            .order(dsl::modified_at.desc())
+            .load_async::<(
+                String,
+                String,
+                String,
+                Option<String>,
+                enums::RoutingAlgorithmKind,
+                PrimitiveDateTime,
+                PrimitiveDateTime,
+            )>(conn)
+            .await
+            .into_report()
+            .change_context(DatabaseError::Others)?
+            .into_iter()
+            .map(
+                |(profile_id, algorithm_id, name, description, kind, created_at, modified_at)| {
+                    RoutingProfileMetadata {
+                        profile_id,
+                        algorithm_id,
+                        name,
+                        description,
+                        kind,
+                        created_at,
+                        modified_at,
+                    }
+                },
+            )
+            .collect())
+    }
+}
diff --git a/crates/diesel_models/src/query/user.rs b/crates/diesel_models/src/query/user.rs
new file mode 100644
index 000000000000..5761d8af814d
--- /dev/null
+++ b/crates/diesel_models/src/query/user.rs
@@ -0,0 +1,62 @@
+use diesel::{associations::HasTable, ExpressionMethods};
+use error_stack::report;
+use router_env::tracing::{self, instrument};
+
+use crate::{
+    errors::{self},
+    query::generics,
+    schema::users::dsl,
+    user::*,
+    PgPooledConn, StorageResult,
+};
+
+impl UserNew {
+    #[instrument(skip(conn))]
+    pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<User> {
+        generics::generic_insert(conn, self).await
+    }
+}
+
+impl User {
+    pub async fn find_by_user_email(conn: &PgPooledConn, user_email: &str) -> StorageResult<Self> {
+        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
+            conn,
+            dsl::email.eq(user_email.to_owned()),
+        )
+        .await
+    }
+
+    pub async fn find_by_user_id(conn: &PgPooledConn, user_id: &str) -> StorageResult<Self> {
+        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
+            conn,
+            dsl::user_id.eq(user_id.to_owned()),
+        )
+        .await
+    }
+
+    pub async fn update_by_user_id(
+        conn: &PgPooledConn,
+        user_id: &str,
+        user: UserUpdate,
+    ) -> StorageResult<Self> {
+        generics::generic_update_with_results::<<Self as HasTable>::Table, _, _, _>(
+            conn,
+            dsl::user_id.eq(user_id.to_owned()),
+            UserUpdateInternal::from(user),
+        )
+        .await?
+        .first()
+        .cloned()
+        .ok_or_else(|| {
+            report!(errors::DatabaseError::NotFound).attach_printable("Error while updating user")
+        })
+    }
+
+    pub async fn delete_by_user_id(conn: &PgPooledConn, user_id: &str) -> StorageResult<bool> {
+        generics::generic_delete::<<Self as HasTable>::Table, _>(
+            conn,
+            dsl::user_id.eq(user_id.to_owned()),
+        )
+        .await
+    }
+}
diff --git a/crates/diesel_models/src/query/user_role.rs b/crates/diesel_models/src/query/user_role.rs
new file mode 100644
index 000000000000..d2f9564a5309
--- /dev/null
+++ b/crates/diesel_models/src/query/user_role.rs
@@ -0,0 +1,58 @@
+use diesel::{associations::HasTable, BoolExpressionMethods, ExpressionMethods};
+use router_env::tracing::{self, instrument};
+
+use crate::{query::generics, schema::user_roles::dsl, user_role::*, PgPooledConn, StorageResult};
+
+impl UserRoleNew {
+    #[instrument(skip(conn))]
+    pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<UserRole> {
+        generics::generic_insert(conn, self).await
+    }
+}
+
+impl UserRole {
+    pub async fn find_by_user_id(conn: &PgPooledConn, user_id: String) -> StorageResult<Self> {
+        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
+            conn,
+            dsl::user_id.eq(user_id),
+        )
+        .await
+    }
+
+    pub async fn update_by_user_id_merchant_id(
+        conn: &PgPooledConn,
+        user_id: String,
+        merchant_id: String,
+        update: UserRoleUpdate,
+    ) -> StorageResult<Self> {
+        generics::generic_update_with_unique_predicate_get_result::<
+            <Self as HasTable>::Table,
+            _,
+            _,
+            _,
+        >(
+            conn,
+            dsl::user_id
+                .eq(user_id)
+                .and(dsl::merchant_id.eq(merchant_id)),
+            UserRoleUpdateInternal::from(update),
+        )
+        .await
+    }
+
+    pub async fn delete_by_user_id(conn: &PgPooledConn, user_id: String) -> StorageResult<bool> {
+        generics::generic_delete::<<Self as HasTable>::Table, _>(conn, dsl::user_id.eq(user_id))
+            .await
+    }
+
+    pub async fn list_by_user_id(conn: &PgPooledConn, user_id: String) -> StorageResult<Vec<Self>> {
+        generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
+            conn,
+            dsl::user_id.eq(user_id),
+            None,
+            None,
+            Some(dsl::created_at.asc()),
+        )
+        .await
+    }
+}
diff --git a/crates/diesel_models/src/refund.rs b/crates/diesel_models/src/refund.rs
index 56adfaf0288a..62aec3fb27d8 100644
--- a/crates/diesel_models/src/refund.rs
+++ b/crates/diesel_models/src/refund.rs
@@ -38,6 +38,7 @@ pub struct Refund {
     pub refund_error_code: Option<String>,
     pub profile_id: Option<String>,
     pub updated_by: String,
+    pub merchant_connector_id: Option<String>,
 }
 
 #[derive(
@@ -79,6 +80,7 @@ pub struct RefundNew {
     pub refund_reason: Option<String>,
     pub profile_id: Option<String>,
     pub updated_by: String,
+    pub merchant_connector_id: Option<String>,
 }
 
 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
@@ -225,3 +227,12 @@ pub struct RefundCoreWorkflow {
     pub merchant_id: String,
     pub payment_id: String,
 }
+
+impl common_utils::events::ApiEventMetric for Refund {
+    fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
+        Some(common_utils::events::ApiEventsType::Refund {
+            payment_id: Some(self.payment_id.clone()),
+            refund_id: self.refund_id.clone(),
+        })
+    }
+}
diff --git a/crates/diesel_models/src/routing_algorithm.rs b/crates/diesel_models/src/routing_algorithm.rs
new file mode 100644
index 000000000000..09f9baf7edb9
--- /dev/null
+++ b/crates/diesel_models/src/routing_algorithm.rs
@@ -0,0 +1,37 @@
+use diesel::{Identifiable, Insertable, Queryable};
+use serde::{Deserialize, Serialize};
+
+use crate::{enums, schema::routing_algorithm};
+
+#[derive(Clone, Debug, Identifiable, Insertable, Queryable, Serialize, Deserialize)]
+#[diesel(table_name = routing_algorithm, primary_key(algorithm_id))]
+pub struct RoutingAlgorithm {
+    pub algorithm_id: String,
+    pub profile_id: String,
+    pub merchant_id: String,
+    pub name: String,
+    pub description: Option<String>,
+    pub kind: enums::RoutingAlgorithmKind,
+    pub algorithm_data: serde_json::Value,
+    pub created_at: time::PrimitiveDateTime,
+    pub modified_at: time::PrimitiveDateTime,
+}
+
+pub struct RoutingAlgorithmMetadata {
+    pub algorithm_id: String,
+    pub name: String,
+    pub description: Option<String>,
+    pub kind: enums::RoutingAlgorithmKind,
+    pub created_at: time::PrimitiveDateTime,
+    pub modified_at: time::PrimitiveDateTime,
+}
+
+pub struct RoutingProfileMetadata {
+    pub profile_id: String,
+    pub algorithm_id: String,
+    pub name: String,
+    pub description: Option<String>,
+    pub kind: enums::RoutingAlgorithmKind,
+    pub created_at: time::PrimitiveDateTime,
+    pub modified_at: time::PrimitiveDateTime,
+}
diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs
index 2cbd6027a7e1..72d5217038c1 100644
--- a/crates/diesel_models/src/schema.rs
+++ b/crates/diesel_models/src/schema.rs
@@ -24,7 +24,7 @@ diesel::table! {
         created_at -> Timestamp,
         modified_at -> Timestamp,
         #[max_length = 64]
-        customer_id -> Varchar,
+        customer_id -> Nullable<Varchar>,
         #[max_length = 64]
         merchant_id -> Varchar,
         #[max_length = 64]
@@ -157,31 +157,6 @@ diesel::table! {
     }
 }
 
-diesel::table! {
-    use diesel::sql_types::*;
-    use crate::enums::diesel_exports::*;
-
-    connector_response (id) {
-        id -> Int4,
-        #[max_length = 64]
-        payment_id -> Varchar,
-        #[max_length = 64]
-        merchant_id -> Varchar,
-        #[max_length = 64]
-        attempt_id -> Varchar,
-        created_at -> Timestamp,
-        modified_at -> Timestamp,
-        #[max_length = 64]
-        connector_name -> Nullable<Varchar>,
-        #[max_length = 128]
-        connector_transaction_id -> Nullable<Varchar>,
-        authentication_data -> Nullable<Json>,
-        encoded_data -> Nullable<Text>,
-        #[max_length = 32]
-        updated_by -> Varchar,
-    }
-}
-
 diesel::table! {
     use diesel::sql_types::*;
     use crate::enums::diesel_exports::*;
@@ -246,6 +221,8 @@ diesel::table! {
         evidence -> Jsonb,
         #[max_length = 64]
         profile_id -> Nullable<Varchar>,
+        #[max_length = 32]
+        merchant_connector_id -> Nullable<Varchar>,
     }
 }
 
@@ -293,6 +270,8 @@ diesel::table! {
         connector_label -> Nullable<Varchar>,
         #[max_length = 64]
         profile_id -> Nullable<Varchar>,
+        #[max_length = 32]
+        merchant_connector_id -> Nullable<Varchar>,
     }
 }
 
@@ -328,6 +307,33 @@ diesel::table! {
     }
 }
 
+diesel::table! {
+    use diesel::sql_types::*;
+    use crate::enums::diesel_exports::*;
+
+    gateway_status_map (connector, flow, sub_flow, code, message) {
+        #[max_length = 64]
+        connector -> Varchar,
+        #[max_length = 64]
+        flow -> Varchar,
+        #[max_length = 64]
+        sub_flow -> Varchar,
+        #[max_length = 255]
+        code -> Varchar,
+        #[max_length = 1024]
+        message -> Varchar,
+        #[max_length = 64]
+        status -> Varchar,
+        #[max_length = 64]
+        router_error -> Nullable<Varchar>,
+        #[max_length = 64]
+        decision -> Varchar,
+        created_at -> Timestamp,
+        last_modified -> Timestamp,
+        step_up_possible -> Bool,
+    }
+}
+
 diesel::table! {
     use diesel::sql_types::*;
     use crate::enums::diesel_exports::*;
@@ -404,6 +410,8 @@ diesel::table! {
         connector_mandate_ids -> Nullable<Jsonb>,
         #[max_length = 64]
         original_payment_id -> Nullable<Varchar>,
+        #[max_length = 32]
+        merchant_connector_id -> Nullable<Varchar>,
     }
 }
 
@@ -499,6 +507,17 @@ diesel::table! {
     }
 }
 
+diesel::table! {
+    use diesel::sql_types::*;
+    use crate::enums::diesel_exports::*;
+
+    organization (org_id) {
+        #[max_length = 32]
+        org_id -> Varchar,
+        org_name -> Nullable<Text>,
+    }
+}
+
 diesel::table! {
     use diesel::sql_types::*;
     use crate::enums::diesel_exports::*;
@@ -559,9 +578,12 @@ diesel::table! {
         #[max_length = 128]
         connector_response_reference_id -> Nullable<Varchar>,
         amount_capturable -> Int8,
-        surcharge_metadata -> Nullable<Jsonb>,
         #[max_length = 32]
         updated_by -> Varchar,
+        #[max_length = 32]
+        merchant_connector_id -> Nullable<Varchar>,
+        authentication_data -> Nullable<Json>,
+        encoded_data -> Nullable<Text>,
     }
 }
 
@@ -622,6 +644,7 @@ diesel::table! {
         payment_confirm_source -> Nullable<PaymentSource>,
         #[max_length = 32]
         updated_by -> Varchar,
+        surcharge_applicable -> Nullable<Bool>,
     }
 }
 
@@ -643,6 +666,8 @@ diesel::table! {
         created_at -> Timestamp,
         last_modified_at -> Timestamp,
         fulfilment_time -> Nullable<Timestamp>,
+        #[max_length = 64]
+        custom_merchant_name -> Nullable<Varchar>,
     }
 }
 
@@ -721,6 +746,8 @@ diesel::table! {
         last_modified_at -> Timestamp,
         #[max_length = 64]
         profile_id -> Nullable<Varchar>,
+        #[max_length = 32]
+        merchant_connector_id -> Nullable<Varchar>,
     }
 }
 
@@ -828,6 +855,8 @@ diesel::table! {
         profile_id -> Nullable<Varchar>,
         #[max_length = 32]
         updated_by -> Varchar,
+        #[max_length = 32]
+        merchant_connector_id -> Nullable<Varchar>,
     }
 }
 
@@ -849,6 +878,73 @@ diesel::table! {
     }
 }
 
+diesel::table! {
+    use diesel::sql_types::*;
+    use crate::enums::diesel_exports::*;
+
+    routing_algorithm (algorithm_id) {
+        #[max_length = 64]
+        algorithm_id -> Varchar,
+        #[max_length = 64]
+        profile_id -> Varchar,
+        #[max_length = 64]
+        merchant_id -> Varchar,
+        #[max_length = 64]
+        name -> Varchar,
+        #[max_length = 256]
+        description -> Nullable<Varchar>,
+        kind -> RoutingAlgorithmKind,
+        algorithm_data -> Jsonb,
+        created_at -> Timestamp,
+        modified_at -> Timestamp,
+    }
+}
+
+diesel::table! {
+    use diesel::sql_types::*;
+    use crate::enums::diesel_exports::*;
+
+    user_roles (id) {
+        id -> Int4,
+        #[max_length = 64]
+        user_id -> Varchar,
+        #[max_length = 64]
+        merchant_id -> Varchar,
+        #[max_length = 64]
+        role_id -> Varchar,
+        #[max_length = 64]
+        org_id -> Varchar,
+        #[max_length = 64]
+        status -> Varchar,
+        #[max_length = 64]
+        created_by -> Varchar,
+        #[max_length = 64]
+        last_modified_by -> Varchar,
+        created_at -> Timestamp,
+        last_modified_at -> Timestamp,
+    }
+}
+
+diesel::table! {
+    use diesel::sql_types::*;
+    use crate::enums::diesel_exports::*;
+
+    users (id) {
+        id -> Int4,
+        #[max_length = 64]
+        user_id -> Varchar,
+        #[max_length = 255]
+        email -> Varchar,
+        #[max_length = 255]
+        name -> Varchar,
+        #[max_length = 255]
+        password -> Varchar,
+        is_verified -> Bool,
+        created_at -> Timestamp,
+        last_modified_at -> Timestamp,
+    }
+}
+
 diesel::allow_tables_to_appear_in_same_query!(
     address,
     api_keys,
@@ -856,17 +952,18 @@ diesel::allow_tables_to_appear_in_same_query!(
     captures,
     cards_info,
     configs,
-    connector_response,
     customers,
     dispute,
     events,
     file_metadata,
     fraud_check,
+    gateway_status_map,
     locker_mock_up,
     mandate,
     merchant_account,
     merchant_connector_account,
     merchant_key_store,
+    organization,
     payment_attempt,
     payment_intent,
     payment_link,
@@ -876,4 +973,7 @@ diesel::allow_tables_to_appear_in_same_query!(
     process_tracker,
     refund,
     reverse_lookup,
+    routing_algorithm,
+    user_roles,
+    users,
 );
diff --git a/crates/diesel_models/src/user.rs b/crates/diesel_models/src/user.rs
new file mode 100644
index 000000000000..6a2e864b291c
--- /dev/null
+++ b/crates/diesel_models/src/user.rs
@@ -0,0 +1,76 @@
+use common_utils::pii;
+use diesel::{AsChangeset, Identifiable, Insertable, Queryable};
+use masking::Secret;
+use time::PrimitiveDateTime;
+
+use crate::schema::users;
+
+#[derive(Clone, Debug, Identifiable, Queryable)]
+#[diesel(table_name = users)]
+pub struct User {
+    pub id: i32,
+    pub user_id: String,
+    pub email: pii::Email,
+    pub name: Secret<String>,
+    pub password: Secret<String>,
+    pub is_verified: bool,
+    pub created_at: PrimitiveDateTime,
+    pub last_modified_at: PrimitiveDateTime,
+}
+
+#[derive(
+    router_derive::Setter, Clone, Debug, Default, Insertable, router_derive::DebugAsDisplay,
+)]
+#[diesel(table_name = users)]
+pub struct UserNew {
+    pub user_id: String,
+    pub email: pii::Email,
+    pub name: Secret<String>,
+    pub password: Secret<String>,
+    pub is_verified: bool,
+    pub created_at: Option<PrimitiveDateTime>,
+    pub last_modified_at: Option<PrimitiveDateTime>,
+}
+
+#[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)]
+#[diesel(table_name = users)]
+pub struct UserUpdateInternal {
+    name: Option<String>,
+    password: Option<Secret<String>>,
+    is_verified: Option<bool>,
+    last_modified_at: PrimitiveDateTime,
+}
+
+#[derive(Debug)]
+pub enum UserUpdate {
+    VerifyUser,
+    AccountUpdate {
+        name: Option<String>,
+        password: Option<Secret<String>>,
+        is_verified: Option<bool>,
+    },
+}
+
+impl From<UserUpdate> for UserUpdateInternal {
+    fn from(user_update: UserUpdate) -> Self {
+        let last_modified_at = common_utils::date_time::now();
+        match user_update {
+            UserUpdate::VerifyUser => Self {
+                name: None,
+                password: None,
+                is_verified: Some(true),
+                last_modified_at,
+            },
+            UserUpdate::AccountUpdate {
+                name,
+                password,
+                is_verified,
+            } => Self {
+                name,
+                password,
+                is_verified,
+                last_modified_at,
+            },
+        }
+    }
+}
diff --git a/crates/diesel_models/src/user_role.rs b/crates/diesel_models/src/user_role.rs
new file mode 100644
index 000000000000..467584ac59db
--- /dev/null
+++ b/crates/diesel_models/src/user_role.rs
@@ -0,0 +1,79 @@
+use diesel::{AsChangeset, Identifiable, Insertable, Queryable};
+use time::PrimitiveDateTime;
+
+use crate::{enums, schema::user_roles};
+
+#[derive(Clone, Debug, Identifiable, Queryable)]
+#[diesel(table_name = user_roles)]
+pub struct UserRole {
+    pub id: i32,
+    pub user_id: String,
+    pub merchant_id: String,
+    pub role_id: String,
+    pub org_id: String,
+    pub status: enums::UserStatus,
+    pub created_by: String,
+    pub last_modified_by: String,
+    pub created_at: PrimitiveDateTime,
+    pub last_modified_at: PrimitiveDateTime,
+}
+
+#[derive(router_derive::Setter, Clone, Debug, Insertable, router_derive::DebugAsDisplay)]
+#[diesel(table_name = user_roles)]
+pub struct UserRoleNew {
+    pub user_id: String,
+    pub merchant_id: String,
+    pub role_id: String,
+    pub org_id: String,
+    pub status: enums::UserStatus,
+    pub created_by: String,
+    pub last_modified_by: String,
+    pub created_at: PrimitiveDateTime,
+    pub last_modified_at: PrimitiveDateTime,
+}
+
+#[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)]
+#[diesel(table_name = user_roles)]
+pub struct UserRoleUpdateInternal {
+    role_id: Option<String>,
+    status: Option<enums::UserStatus>,
+    last_modified_by: Option<String>,
+    last_modified_at: PrimitiveDateTime,
+}
+
+pub enum UserRoleUpdate {
+    UpdateStatus {
+        status: enums::UserStatus,
+        modified_by: String,
+    },
+    UpdateRole {
+        role_id: String,
+        modified_by: String,
+    },
+}
+
+impl From<UserRoleUpdate> for UserRoleUpdateInternal {
+    fn from(value: UserRoleUpdate) -> Self {
+        let last_modified_at = common_utils::date_time::now();
+        match value {
+            UserRoleUpdate::UpdateRole {
+                role_id,
+                modified_by,
+            } => Self {
+                role_id: Some(role_id),
+                last_modified_by: Some(modified_by),
+                status: None,
+                last_modified_at,
+            },
+            UserRoleUpdate::UpdateStatus {
+                status,
+                modified_by,
+            } => Self {
+                status: Some(status),
+                last_modified_at,
+                last_modified_by: Some(modified_by),
+                role_id: None,
+            },
+        }
+    }
+}
diff --git a/crates/drainer/Cargo.toml b/crates/drainer/Cargo.toml
index 3bf056a69b38..668e8b0574fe 100644
--- a/crates/drainer/Cargo.toml
+++ b/crates/drainer/Cargo.toml
@@ -8,12 +8,12 @@ readme = "README.md"
 license.workspace = true
 
 [features]
-release = ["kms","vergen"]
+release = ["kms", "vergen"]
 kms = ["external_services/kms"]
 vergen = ["router_env/vergen"]
 
 [dependencies]
-async-bb8-diesel = "0.1.0"
+async-bb8-diesel = { git = "https://github.com/jarnura/async-bb8-diesel", rev = "53b4ab901aab7635c8215fd1c2d542c8db443094" }
 bb8 = "0.8"
 clap = { version = "4.3.2", default-features = false, features = ["std", "derive", "help", "usage"] }
 config = { version = "0.13.3", features = ["toml"] }
@@ -28,11 +28,11 @@ tokio = { version = "1.28.2", features = ["macros", "rt-multi-thread"] }
 
 # First Party Crates
 common_utils = { version = "0.1.0", path = "../common_utils", features = ["signals"] }
+diesel_models = { version = "0.1.0", path = "../diesel_models", features = ["kv_store"] }
 external_services = { version = "0.1.0", path = "../external_services" }
 masking = { version = "0.1.0", path = "../masking" }
 redis_interface = { version = "0.1.0", path = "../redis_interface" }
 router_env = { version = "0.1.0", path = "../router_env", features = ["log_extra_implicit_fields", "log_custom_entries_to_extra"] }
-diesel_models = { version = "0.1.0", path = "../diesel_models", features = ["kv_store"] }
 
 [build-dependencies]
 router_env = { version = "0.1.0", path = "../router_env", default-features = false }
diff --git a/crates/drainer/src/lib.rs b/crates/drainer/src/lib.rs
index 7dcbc2c518cf..7ccfd600d662 100644
--- a/crates/drainer/src/lib.rs
+++ b/crates/drainer/src/lib.rs
@@ -10,6 +10,7 @@ use std::sync::{atomic, Arc};
 use common_utils::signals::get_allowed_signals;
 use diesel_models::kv;
 use error_stack::{IntoReport, ResultExt};
+use router_env::{instrument, tracing};
 use tokio::sync::{mpsc, oneshot};
 
 use crate::{connection::pg_connection, services::Store};
@@ -122,6 +123,7 @@ async fn drainer_handler(
     active_tasks.fetch_add(1, atomic::Ordering::Release);
 
     let stream_name = utils::get_drainer_stream_name(store.clone(), stream_index);
+
     let drainer_result =
         Box::pin(drainer(store.clone(), max_read_count, stream_name.as_str())).await;
 
@@ -130,6 +132,7 @@ async fn drainer_handler(
     }
 
     let flag_stream_name = utils::get_stream_key_flag(store.clone(), stream_index);
+
     //TODO: USE THE RESULT FOR LOGGING
     let output =
         utils::make_stream_available(flag_stream_name.as_str(), store.redis_conn.as_ref()).await;
@@ -137,6 +140,7 @@ async fn drainer_handler(
     output
 }
 
+#[instrument(skip_all, fields(global_id, request_id, session_id))]
 async fn drainer(
     store: Arc<Store>,
     max_read_count: u64,
@@ -174,9 +178,21 @@ async fn drainer(
         }],
     );
 
+    let session_id = common_utils::generate_id_with_default_len("drainer_session");
+
     // TODO: Handle errors when deserialization fails and when DB error occurs
     for entry in entries {
         let typed_sql = entry.1.get("typed_sql").map_or(String::new(), Clone::clone);
+        let request_id = entry
+            .1
+            .get("request_id")
+            .map_or(String::new(), Clone::clone);
+        let global_id = entry.1.get("global_id").map_or(String::new(), Clone::clone);
+
+        tracing::Span::current().record("request_id", request_id);
+        tracing::Span::current().record("global_id", global_id);
+        tracing::Span::current().record("session_id", &session_id);
+
         let result = serde_json::from_str::<kv::DBOperation>(&typed_sql);
         let db_op = match result {
             Ok(f) => f,
@@ -190,7 +206,6 @@ async fn drainer(
         let payment_attempt = "payment_attempt";
         let refund = "refund";
         let reverse_lookup = "reverse_lookup";
-        let connector_response = "connector_response";
         let address = "address";
         match db_op {
             // TODO: Handle errors
@@ -214,13 +229,6 @@ async fn drainer(
                         kv::Insertable::Refund(a) => {
                             macro_util::handle_resp!(a.insert(&conn).await, insert_op, refund)
                         }
-                        kv::Insertable::ConnectorResponse(a) => {
-                            macro_util::handle_resp!(
-                                a.insert(&conn).await,
-                                insert_op,
-                                connector_response
-                            )
-                        }
                         kv::Insertable::Address(addr) => {
                             macro_util::handle_resp!(addr.insert(&conn).await, insert_op, address)
                         }
@@ -267,11 +275,6 @@ async fn drainer(
                                 refund
                             )
                         }
-                        kv::Updateable::ConnectorResponseUpdate(a) => macro_util::handle_resp!(
-                            a.orig.update(&conn, a.update_data).await,
-                            update_op,
-                            connector_response
-                        ),
                         kv::Updateable::AddressUpdate(a) => macro_util::handle_resp!(
                             a.orig.update(&conn, a.update_data).await,
                             update_op,
diff --git a/crates/drainer/src/services.rs b/crates/drainer/src/services.rs
index 6edec31f26d7..73f66f27dbf5 100644
--- a/crates/drainer/src/services.rs
+++ b/crates/drainer/src/services.rs
@@ -7,6 +7,7 @@ pub struct Store {
     pub master_pool: PgPool,
     pub redis_conn: Arc<redis_interface::RedisConnectionPool>,
     pub config: StoreConfig,
+    pub request_id: Option<String>,
 }
 
 #[derive(Clone)]
@@ -30,6 +31,7 @@ impl Store {
                 drainer_stream_name: config.drainer.stream_name.clone(),
                 drainer_num_partitions: config.drainer.num_partitions,
             },
+            request_id: None,
         }
     }
 
diff --git a/crates/euclid/Cargo.toml b/crates/euclid/Cargo.toml
new file mode 100644
index 000000000000..859795964145
--- /dev/null
+++ b/crates/euclid/Cargo.toml
@@ -0,0 +1,36 @@
+[package]
+name = "euclid"
+description = "DSL for static routing"
+version = "0.1.0"
+edition.workspace = true
+rust-version.workspace = true
+
+[dependencies]
+erased-serde = "0.3.28"
+frunk = "0.4.1"
+frunk_core = "0.4.1"
+nom = { version = "7.1.3", features = ["alloc"], optional = true }
+once_cell = "1.18.0"
+rustc-hash = "1.1.0"
+serde = { version = "1.0.163", features = ["derive", "rc"] }
+serde_json = "1.0.96"
+strum = { version = "0.25", features = ["derive"] }
+thiserror = "1.0.43"
+
+# First party dependencies
+common_enums = { version = "0.1.0", path = "../common_enums" }
+euclid_macros = { version = "0.1.0", path = "../euclid_macros" }
+
+[features]
+ast_parser = ["dep:nom"]
+valued_jit = []
+connector_choice_mca_id = []
+dummy_connector = []
+
+[dev-dependencies]
+criterion = "0.5"
+
+[[bench]]
+name = "backends"
+harness = false
+required-features = ["ast_parser", "valued_jit"]
diff --git a/crates/euclid/benches/backends.rs b/crates/euclid/benches/backends.rs
new file mode 100644
index 000000000000..9d29c41d34c6
--- /dev/null
+++ b/crates/euclid/benches/backends.rs
@@ -0,0 +1,93 @@
+#![allow(unused, clippy::expect_used)]
+
+use criterion::{black_box, criterion_group, criterion_main, Criterion};
+use euclid::{
+    backend::{inputs, EuclidBackend, InterpreterBackend, VirInterpreterBackend},
+    enums,
+    frontend::ast::{self, parser},
+    types::DummyOutput,
+};
+
+fn get_program_data() -> (ast::Program<DummyOutput>, inputs::BackendInput) {
+    let code1 = r#"
+        default: ["stripe", "adyen", "checkout"]
+
+        stripe_first: ["stripe", "aci"]
+        {
+            payment_method = card & amount = 40 {
+                payment_method = (card, bank_redirect)
+                amount = (40, 50)
+            }
+        }
+
+        adyen_first: ["adyen", "checkout"]
+        {
+            payment_method = bank_redirect & amount > 60 {
+                payment_method = (card, bank_redirect)
+                amount = (40, 50)
+            }
+        }
+
+        auth_first: ["authorizedotnet", "adyen"]
+        {
+            payment_method = wallet
+        }
+    "#;
+
+    let inp = inputs::BackendInput {
+        metadata: None,
+        payment: inputs::PaymentInput {
+            amount: 32,
+            card_bin: None,
+            currency: enums::Currency::USD,
+            authentication_type: Some(enums::AuthenticationType::NoThreeDs),
+            capture_method: Some(enums::CaptureMethod::Automatic),
+            business_country: Some(enums::Country::UnitedStatesOfAmerica),
+            billing_country: Some(enums::Country::France),
+            business_label: None,
+            setup_future_usage: None,
+        },
+        payment_method: inputs::PaymentMethodInput {
+            payment_method: Some(enums::PaymentMethod::PayLater),
+            payment_method_type: Some(enums::PaymentMethodType::Sofort),
+            card_network: None,
+        },
+        mandate: inputs::MandateData {
+            mandate_acceptance_type: None,
+            mandate_type: None,
+            payment_type: None,
+        },
+    };
+
+    let (_, program) = parser::program(code1).expect("Parser");
+
+    (program, inp)
+}
+
+fn interpreter_vs_jit_vs_vir_interpreter(c: &mut Criterion) {
+    let (program, binputs) = get_program_data();
+
+    let interp_b = InterpreterBackend::with_program(program.clone()).expect("Interpreter backend");
+
+    let vir_interp_b =
+        VirInterpreterBackend::with_program(program).expect("Vir Interpreter Backend");
+
+    c.bench_function("Raw Interpreter Backend", |b| {
+        b.iter(|| {
+            interp_b
+                .execute(binputs.clone())
+                .expect("Interpreter EXECUTION");
+        });
+    });
+
+    c.bench_function("Valued Interpreter Backend", |b| {
+        b.iter(|| {
+            vir_interp_b
+                .execute(binputs.clone())
+                .expect("Vir Interpreter execution");
+        })
+    });
+}
+
+criterion_group!(benches, interpreter_vs_jit_vs_vir_interpreter);
+criterion_main!(benches);
diff --git a/crates/euclid/src/backend.rs b/crates/euclid/src/backend.rs
new file mode 100644
index 000000000000..caf0a87b69cb
--- /dev/null
+++ b/crates/euclid/src/backend.rs
@@ -0,0 +1,25 @@
+pub mod inputs;
+pub mod interpreter;
+#[cfg(feature = "valued_jit")]
+pub mod vir_interpreter;
+
+pub use inputs::BackendInput;
+pub use interpreter::InterpreterBackend;
+#[cfg(feature = "valued_jit")]
+pub use vir_interpreter::VirInterpreterBackend;
+
+use crate::frontend::ast;
+
+#[derive(Debug, Clone, serde::Serialize)]
+pub struct BackendOutput<O> {
+    pub rule_name: Option<String>,
+    pub connector_selection: O,
+}
+
+pub trait EuclidBackend<O>: Sized {
+    type Error: serde::Serialize;
+
+    fn with_program(program: ast::Program<O>) -> Result<Self, Self::Error>;
+
+    fn execute(&self, input: BackendInput) -> Result<BackendOutput<O>, Self::Error>;
+}
diff --git a/crates/euclid/src/backend/inputs.rs b/crates/euclid/src/backend/inputs.rs
new file mode 100644
index 000000000000..18298d4c358d
--- /dev/null
+++ b/crates/euclid/src/backend/inputs.rs
@@ -0,0 +1,39 @@
+use rustc_hash::FxHashMap;
+use serde::{Deserialize, Serialize};
+
+use crate::enums;
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct MandateData {
+    pub mandate_acceptance_type: Option<enums::MandateAcceptanceType>,
+    pub mandate_type: Option<enums::MandateType>,
+    pub payment_type: Option<enums::PaymentType>,
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct PaymentMethodInput {
+    pub payment_method: Option<enums::PaymentMethod>,
+    pub payment_method_type: Option<enums::PaymentMethodType>,
+    pub card_network: Option<enums::CardNetwork>,
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct PaymentInput {
+    pub amount: i64,
+    pub currency: enums::Currency,
+    pub authentication_type: Option<enums::AuthenticationType>,
+    pub card_bin: Option<String>,
+    pub capture_method: Option<enums::CaptureMethod>,
+    pub business_country: Option<enums::Country>,
+    pub billing_country: Option<enums::Country>,
+    pub business_label: Option<String>,
+    pub setup_future_usage: Option<enums::SetupFutureUsage>,
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct BackendInput {
+    pub metadata: Option<FxHashMap<String, String>>,
+    pub payment: PaymentInput,
+    pub payment_method: PaymentMethodInput,
+    pub mandate: MandateData,
+}
diff --git a/crates/euclid/src/backend/interpreter.rs b/crates/euclid/src/backend/interpreter.rs
new file mode 100644
index 000000000000..bf0a561bf3f3
--- /dev/null
+++ b/crates/euclid/src/backend/interpreter.rs
@@ -0,0 +1,180 @@
+pub mod types;
+
+use crate::{
+    backend::{self, inputs, EuclidBackend},
+    frontend::ast,
+};
+
+pub struct InterpreterBackend<O> {
+    program: ast::Program<O>,
+}
+
+impl<O> InterpreterBackend<O>
+where
+    O: Clone,
+{
+    fn eval_number_comparison_array(
+        num: i64,
+        array: &[ast::NumberComparison],
+    ) -> Result<bool, types::InterpreterError> {
+        for comparison in array {
+            let other = comparison.number;
+            let res = match comparison.comparison_type {
+                ast::ComparisonType::GreaterThan => num > other,
+                ast::ComparisonType::LessThan => num < other,
+                ast::ComparisonType::LessThanEqual => num <= other,
+                ast::ComparisonType::GreaterThanEqual => num >= other,
+                ast::ComparisonType::Equal => num == other,
+                ast::ComparisonType::NotEqual => num != other,
+            };
+
+            if res {
+                return Ok(true);
+            }
+        }
+
+        Ok(false)
+    }
+
+    fn eval_comparison(
+        comparison: &ast::Comparison,
+        ctx: &types::Context,
+    ) -> Result<bool, types::InterpreterError> {
+        use ast::{ComparisonType::*, ValueType::*};
+
+        let value = ctx
+            .get(&comparison.lhs)
+            .ok_or_else(|| types::InterpreterError {
+                error_type: types::InterpreterErrorType::InvalidKey(comparison.lhs.clone()),
+                metadata: comparison.metadata.clone(),
+            })?;
+
+        if let Some(val) = value {
+            match (val, &comparison.comparison, &comparison.value) {
+                (EnumVariant(e1), Equal, EnumVariant(e2)) => Ok(e1 == e2),
+                (EnumVariant(e1), NotEqual, EnumVariant(e2)) => Ok(e1 != e2),
+                (EnumVariant(e), Equal, EnumVariantArray(evec)) => Ok(evec.iter().any(|v| e == v)),
+                (EnumVariant(e), NotEqual, EnumVariantArray(evec)) => {
+                    Ok(evec.iter().all(|v| e != v))
+                }
+                (Number(n1), Equal, Number(n2)) => Ok(n1 == n2),
+                (Number(n1), NotEqual, Number(n2)) => Ok(n1 != n2),
+                (Number(n1), LessThanEqual, Number(n2)) => Ok(n1 <= n2),
+                (Number(n1), GreaterThanEqual, Number(n2)) => Ok(n1 >= n2),
+                (Number(n1), LessThan, Number(n2)) => Ok(n1 < n2),
+                (Number(n1), GreaterThan, Number(n2)) => Ok(n1 > n2),
+                (Number(n), Equal, NumberArray(nvec)) => Ok(nvec.iter().any(|v| v == n)),
+                (Number(n), NotEqual, NumberArray(nvec)) => Ok(nvec.iter().all(|v| v != n)),
+                (Number(n), Equal, NumberComparisonArray(ncvec)) => {
+                    Self::eval_number_comparison_array(*n, ncvec)
+                }
+                _ => Err(types::InterpreterError {
+                    error_type: types::InterpreterErrorType::InvalidComparison,
+                    metadata: comparison.metadata.clone(),
+                }),
+            }
+        } else {
+            Ok(false)
+        }
+    }
+
+    fn eval_if_condition(
+        condition: &ast::IfCondition,
+        ctx: &types::Context,
+    ) -> Result<bool, types::InterpreterError> {
+        for comparison in condition {
+            let res = Self::eval_comparison(comparison, ctx)?;
+
+            if !res {
+                return Ok(false);
+            }
+        }
+
+        Ok(true)
+    }
+
+    fn eval_if_statement(
+        stmt: &ast::IfStatement,
+        ctx: &types::Context,
+    ) -> Result<bool, types::InterpreterError> {
+        let cond_res = Self::eval_if_condition(&stmt.condition, ctx)?;
+
+        if !cond_res {
+            return Ok(false);
+        }
+
+        if let Some(ref nested) = stmt.nested {
+            for nested_if in nested {
+                let res = Self::eval_if_statement(nested_if, ctx)?;
+
+                if res {
+                    return Ok(true);
+                }
+            }
+
+            return Ok(false);
+        }
+
+        Ok(true)
+    }
+
+    fn eval_rule_statements(
+        statements: &[ast::IfStatement],
+        ctx: &types::Context,
+    ) -> Result<bool, types::InterpreterError> {
+        for stmt in statements {
+            let res = Self::eval_if_statement(stmt, ctx)?;
+
+            if res {
+                return Ok(true);
+            }
+        }
+
+        Ok(false)
+    }
+
+    #[inline]
+    fn eval_rule(
+        rule: &ast::Rule<O>,
+        ctx: &types::Context,
+    ) -> Result<bool, types::InterpreterError> {
+        Self::eval_rule_statements(&rule.statements, ctx)
+    }
+
+    fn eval_program(
+        program: &ast::Program<O>,
+        ctx: &types::Context,
+    ) -> Result<backend::BackendOutput<O>, types::InterpreterError> {
+        for rule in &program.rules {
+            let res = Self::eval_rule(rule, ctx)?;
+
+            if res {
+                return Ok(backend::BackendOutput {
+                    connector_selection: rule.connector_selection.clone(),
+                    rule_name: Some(rule.name.clone()),
+                });
+            }
+        }
+
+        Ok(backend::BackendOutput {
+            connector_selection: program.default_selection.clone(),
+            rule_name: None,
+        })
+    }
+}
+
+impl<O> EuclidBackend<O> for InterpreterBackend<O>
+where
+    O: Clone,
+{
+    type Error = types::InterpreterError;
+
+    fn with_program(program: ast::Program<O>) -> Result<Self, Self::Error> {
+        Ok(Self { program })
+    }
+
+    fn execute(&self, input: inputs::BackendInput) -> Result<super::BackendOutput<O>, Self::Error> {
+        let ctx: types::Context = input.into();
+        Self::eval_program(&self.program, &ctx)
+    }
+}
diff --git a/crates/euclid/src/backend/interpreter/types.rs b/crates/euclid/src/backend/interpreter/types.rs
new file mode 100644
index 000000000000..a6384dbdf3ce
--- /dev/null
+++ b/crates/euclid/src/backend/interpreter/types.rs
@@ -0,0 +1,81 @@
+use std::{collections::HashMap, fmt, ops::Deref, string::ToString};
+
+use serde::Serialize;
+
+use crate::{backend::inputs, frontend::ast::ValueType, types::EuclidKey};
+
+#[derive(Debug, Clone, Serialize, thiserror::Error)]
+#[serde(tag = "type", content = "data", rename_all = "snake_case")]
+pub enum InterpreterErrorType {
+    #[error("Invalid key received '{0}'")]
+    InvalidKey(String),
+    #[error("Invalid Comparison")]
+    InvalidComparison,
+}
+
+#[derive(Debug, Clone, Serialize, thiserror::Error)]
+pub struct InterpreterError {
+    pub error_type: InterpreterErrorType,
+    pub metadata: HashMap<String, serde_json::Value>,
+}
+
+impl fmt::Display for InterpreterError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        InterpreterErrorType::fmt(&self.error_type, f)
+    }
+}
+
+pub struct Context(HashMap<String, Option<ValueType>>);
+
+impl Deref for Context {
+    type Target = HashMap<String, Option<ValueType>>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl From<inputs::BackendInput> for Context {
+    fn from(input: inputs::BackendInput) -> Self {
+        let ctx = HashMap::<String, Option<ValueType>>::from_iter([
+            (
+                EuclidKey::PaymentMethod.to_string(),
+                input
+                    .payment_method
+                    .payment_method
+                    .map(|pm| ValueType::EnumVariant(pm.to_string())),
+            ),
+            (
+                EuclidKey::PaymentMethodType.to_string(),
+                input
+                    .payment_method
+                    .payment_method_type
+                    .map(|pt| ValueType::EnumVariant(pt.to_string())),
+            ),
+            (
+                EuclidKey::AuthenticationType.to_string(),
+                input
+                    .payment
+                    .authentication_type
+                    .map(|at| ValueType::EnumVariant(at.to_string())),
+            ),
+            (
+                EuclidKey::CaptureMethod.to_string(),
+                input
+                    .payment
+                    .capture_method
+                    .map(|cm| ValueType::EnumVariant(cm.to_string())),
+            ),
+            (
+                EuclidKey::PaymentAmount.to_string(),
+                Some(ValueType::Number(input.payment.amount)),
+            ),
+            (
+                EuclidKey::PaymentCurrency.to_string(),
+                Some(ValueType::EnumVariant(input.payment.currency.to_string())),
+            ),
+        ]);
+
+        Self(ctx)
+    }
+}
diff --git a/crates/euclid/src/backend/vir_interpreter.rs b/crates/euclid/src/backend/vir_interpreter.rs
new file mode 100644
index 000000000000..b7be62cf6740
--- /dev/null
+++ b/crates/euclid/src/backend/vir_interpreter.rs
@@ -0,0 +1,583 @@
+pub mod types;
+
+use crate::{
+    backend::{self, inputs, EuclidBackend},
+    frontend::{
+        ast,
+        dir::{self, EuclidDirFilter},
+        vir,
+    },
+};
+
+pub struct VirInterpreterBackend<O> {
+    program: vir::ValuedProgram<O>,
+}
+
+impl<O> VirInterpreterBackend<O>
+where
+    O: Clone,
+{
+    #[inline]
+    fn eval_comparison(comp: &vir::ValuedComparison, ctx: &types::Context) -> bool {
+        match &comp.logic {
+            vir::ValuedComparisonLogic::PositiveDisjunction => {
+                comp.values.iter().any(|v| ctx.check_presence(v))
+            }
+            vir::ValuedComparisonLogic::NegativeConjunction => {
+                comp.values.iter().all(|v| !ctx.check_presence(v))
+            }
+        }
+    }
+
+    #[inline]
+    fn eval_condition(cond: &vir::ValuedIfCondition, ctx: &types::Context) -> bool {
+        cond.iter().all(|comp| Self::eval_comparison(comp, ctx))
+    }
+
+    fn eval_statement(stmt: &vir::ValuedIfStatement, ctx: &types::Context) -> bool {
+        Self::eval_condition(&stmt.condition, ctx)
+            .then(|| {
+                stmt.nested.as_ref().map_or(true, |nested_stmts| {
+                    nested_stmts.iter().any(|s| Self::eval_statement(s, ctx))
+                })
+            })
+            .unwrap_or(false)
+    }
+
+    fn eval_rule(rule: &vir::ValuedRule<O>, ctx: &types::Context) -> bool {
+        rule.statements
+            .iter()
+            .any(|stmt| Self::eval_statement(stmt, ctx))
+    }
+
+    fn eval_program(
+        program: &vir::ValuedProgram<O>,
+        ctx: &types::Context,
+    ) -> backend::BackendOutput<O> {
+        program
+            .rules
+            .iter()
+            .find(|rule| Self::eval_rule(rule, ctx))
+            .map_or_else(
+                || backend::BackendOutput {
+                    connector_selection: program.default_selection.clone(),
+                    rule_name: None,
+                },
+                |rule| backend::BackendOutput {
+                    connector_selection: rule.connector_selection.clone(),
+                    rule_name: Some(rule.name.clone()),
+                },
+            )
+    }
+}
+
+impl<O> EuclidBackend<O> for VirInterpreterBackend<O>
+where
+    O: Clone + EuclidDirFilter,
+{
+    type Error = types::VirInterpreterError;
+
+    fn with_program(program: ast::Program<O>) -> Result<Self, Self::Error> {
+        let dir_program = ast::lowering::lower_program(program)
+            .map_err(types::VirInterpreterError::LoweringError)?;
+
+        let vir_program = dir::lowering::lower_program(dir_program)
+            .map_err(types::VirInterpreterError::LoweringError)?;
+
+        Ok(Self {
+            program: vir_program,
+        })
+    }
+
+    fn execute(
+        &self,
+        input: inputs::BackendInput,
+    ) -> Result<backend::BackendOutput<O>, Self::Error> {
+        let ctx = types::Context::from_input(input);
+        Ok(Self::eval_program(&self.program, &ctx))
+    }
+}
+#[cfg(all(test, feature = "ast_parser"))]
+mod test {
+    #![allow(clippy::expect_used)]
+    use rustc_hash::FxHashMap;
+
+    use super::*;
+    use crate::{enums, types::DummyOutput};
+
+    #[test]
+    fn test_execution() {
+        let program_str = r#"
+        default: [ "stripe",  "adyen"]
+
+        rule_1: ["stripe"]
+        {
+            pay_later = klarna
+        }
+
+        rule_2: ["adyen"]
+        {
+            pay_later = affirm
+        }
+        "#;
+
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let inp = inputs::BackendInput {
+            metadata: None,
+            payment: inputs::PaymentInput {
+                amount: 32,
+                card_bin: None,
+                currency: enums::Currency::USD,
+                authentication_type: Some(enums::AuthenticationType::NoThreeDs),
+                capture_method: Some(enums::CaptureMethod::Automatic),
+                business_country: Some(enums::Country::UnitedStatesOfAmerica),
+                billing_country: Some(enums::Country::France),
+                business_label: None,
+                setup_future_usage: None,
+            },
+            payment_method: inputs::PaymentMethodInput {
+                payment_method: Some(enums::PaymentMethod::PayLater),
+                payment_method_type: Some(enums::PaymentMethodType::Affirm),
+                card_network: None,
+            },
+            mandate: inputs::MandateData {
+                mandate_acceptance_type: None,
+                mandate_type: None,
+                payment_type: None,
+            },
+        };
+
+        let backend = VirInterpreterBackend::<DummyOutput>::with_program(program).expect("Program");
+        let result = backend.execute(inp).expect("Execution");
+        assert_eq!(result.rule_name.expect("Rule Name").as_str(), "rule_2");
+    }
+    #[test]
+    fn test_payment_type() {
+        let program_str = r#"
+        default: ["stripe", "adyen"]
+        rule_1: ["stripe"]
+        {
+           payment_type = setup_mandate
+        }
+        "#;
+
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let inp = inputs::BackendInput {
+            metadata: None,
+            payment: inputs::PaymentInput {
+                amount: 32,
+                currency: enums::Currency::USD,
+                card_bin: Some("123456".to_string()),
+                authentication_type: Some(enums::AuthenticationType::NoThreeDs),
+                capture_method: Some(enums::CaptureMethod::Automatic),
+                business_country: Some(enums::Country::UnitedStatesOfAmerica),
+                billing_country: Some(enums::Country::France),
+                business_label: None,
+                setup_future_usage: None,
+            },
+            payment_method: inputs::PaymentMethodInput {
+                payment_method: Some(enums::PaymentMethod::PayLater),
+                payment_method_type: Some(enums::PaymentMethodType::Affirm),
+                card_network: None,
+            },
+            mandate: inputs::MandateData {
+                mandate_acceptance_type: None,
+                mandate_type: None,
+                payment_type: Some(enums::PaymentType::SetupMandate),
+            },
+        };
+
+        let backend = VirInterpreterBackend::<DummyOutput>::with_program(program).expect("Program");
+        let result = backend.execute(inp).expect("Execution");
+        assert_eq!(result.rule_name.expect("Rule Name").as_str(), "rule_1");
+    }
+
+    #[test]
+    fn test_mandate_type() {
+        let program_str = r#"
+        default: ["stripe", "adyen"]
+        rule_1: ["stripe"]
+        {
+           mandate_type = single_use
+        }
+        "#;
+
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let inp = inputs::BackendInput {
+            metadata: None,
+            payment: inputs::PaymentInput {
+                amount: 32,
+                currency: enums::Currency::USD,
+                card_bin: Some("123456".to_string()),
+                authentication_type: Some(enums::AuthenticationType::NoThreeDs),
+                capture_method: Some(enums::CaptureMethod::Automatic),
+                business_country: Some(enums::Country::UnitedStatesOfAmerica),
+                billing_country: Some(enums::Country::France),
+                business_label: None,
+                setup_future_usage: None,
+            },
+            payment_method: inputs::PaymentMethodInput {
+                payment_method: Some(enums::PaymentMethod::PayLater),
+                payment_method_type: Some(enums::PaymentMethodType::Affirm),
+                card_network: None,
+            },
+            mandate: inputs::MandateData {
+                mandate_acceptance_type: None,
+                mandate_type: Some(enums::MandateType::SingleUse),
+                payment_type: None,
+            },
+        };
+
+        let backend = VirInterpreterBackend::<DummyOutput>::with_program(program).expect("Program");
+        let result = backend.execute(inp).expect("Execution");
+        assert_eq!(result.rule_name.expect("Rule Name").as_str(), "rule_1");
+    }
+
+    #[test]
+    fn test_mandate_acceptance_type() {
+        let program_str = r#"
+        default: ["stripe","adyen"]
+        rule_1: ["stripe"]
+        {
+           mandate_acceptance_type = online
+        }
+        "#;
+
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let inp = inputs::BackendInput {
+            metadata: None,
+            payment: inputs::PaymentInput {
+                amount: 32,
+                currency: enums::Currency::USD,
+                card_bin: Some("123456".to_string()),
+                authentication_type: Some(enums::AuthenticationType::NoThreeDs),
+                capture_method: Some(enums::CaptureMethod::Automatic),
+                business_country: Some(enums::Country::UnitedStatesOfAmerica),
+                billing_country: Some(enums::Country::France),
+                business_label: None,
+                setup_future_usage: None,
+            },
+            payment_method: inputs::PaymentMethodInput {
+                payment_method: Some(enums::PaymentMethod::PayLater),
+                payment_method_type: Some(enums::PaymentMethodType::Affirm),
+                card_network: None,
+            },
+            mandate: inputs::MandateData {
+                mandate_acceptance_type: Some(enums::MandateAcceptanceType::Online),
+                mandate_type: None,
+                payment_type: None,
+            },
+        };
+
+        let backend = VirInterpreterBackend::<DummyOutput>::with_program(program).expect("Program");
+        let result = backend.execute(inp).expect("Execution");
+        assert_eq!(result.rule_name.expect("Rule Name").as_str(), "rule_1");
+    }
+    #[test]
+    fn test_card_bin() {
+        let program_str = r#"
+        default: ["stripe", "adyen"]
+
+        rule_1: ["stripe"]
+        {
+           card_bin="123456"
+        }
+        "#;
+
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let inp = inputs::BackendInput {
+            metadata: None,
+            payment: inputs::PaymentInput {
+                amount: 32,
+                currency: enums::Currency::USD,
+                card_bin: Some("123456".to_string()),
+                authentication_type: Some(enums::AuthenticationType::NoThreeDs),
+                capture_method: Some(enums::CaptureMethod::Automatic),
+                business_country: Some(enums::Country::UnitedStatesOfAmerica),
+                billing_country: Some(enums::Country::France),
+                business_label: None,
+                setup_future_usage: None,
+            },
+            payment_method: inputs::PaymentMethodInput {
+                payment_method: Some(enums::PaymentMethod::PayLater),
+                payment_method_type: Some(enums::PaymentMethodType::Affirm),
+                card_network: None,
+            },
+            mandate: inputs::MandateData {
+                mandate_acceptance_type: None,
+                mandate_type: None,
+                payment_type: None,
+            },
+        };
+
+        let backend = VirInterpreterBackend::<DummyOutput>::with_program(program).expect("Program");
+        let result = backend.execute(inp).expect("Execution");
+        assert_eq!(result.rule_name.expect("Rule Name").as_str(), "rule_1");
+    }
+    #[test]
+    fn test_payment_amount() {
+        let program_str = r#"
+        default: ["stripe", "adyen"]
+
+        rule_1: ["stripe"]
+        {
+           amount = 32
+        }
+        "#;
+
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let inp = inputs::BackendInput {
+            metadata: None,
+            payment: inputs::PaymentInput {
+                amount: 32,
+                currency: enums::Currency::USD,
+                card_bin: None,
+                authentication_type: Some(enums::AuthenticationType::NoThreeDs),
+                capture_method: Some(enums::CaptureMethod::Automatic),
+                business_country: Some(enums::Country::UnitedStatesOfAmerica),
+                billing_country: Some(enums::Country::France),
+                business_label: None,
+                setup_future_usage: None,
+            },
+            payment_method: inputs::PaymentMethodInput {
+                payment_method: Some(enums::PaymentMethod::PayLater),
+                payment_method_type: Some(enums::PaymentMethodType::Affirm),
+                card_network: None,
+            },
+            mandate: inputs::MandateData {
+                mandate_acceptance_type: None,
+                mandate_type: None,
+                payment_type: None,
+            },
+        };
+
+        let backend = VirInterpreterBackend::<DummyOutput>::with_program(program).expect("Program");
+        let result = backend.execute(inp).expect("Execution");
+        assert_eq!(result.rule_name.expect("Rule Name").as_str(), "rule_1");
+    }
+    #[test]
+    fn test_payment_method() {
+        let program_str = r#"
+        default: ["stripe", "adyen"]
+
+        rule_1: ["stripe"]
+        {
+           payment_method = pay_later
+        }
+        "#;
+
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let inp = inputs::BackendInput {
+            metadata: None,
+            payment: inputs::PaymentInput {
+                amount: 32,
+                currency: enums::Currency::USD,
+                card_bin: None,
+                authentication_type: Some(enums::AuthenticationType::NoThreeDs),
+                capture_method: Some(enums::CaptureMethod::Automatic),
+                business_country: Some(enums::Country::UnitedStatesOfAmerica),
+                billing_country: Some(enums::Country::France),
+                business_label: None,
+                setup_future_usage: None,
+            },
+            payment_method: inputs::PaymentMethodInput {
+                payment_method: Some(enums::PaymentMethod::PayLater),
+                payment_method_type: Some(enums::PaymentMethodType::Affirm),
+                card_network: None,
+            },
+            mandate: inputs::MandateData {
+                mandate_acceptance_type: None,
+                mandate_type: None,
+                payment_type: None,
+            },
+        };
+
+        let backend = VirInterpreterBackend::<DummyOutput>::with_program(program).expect("Program");
+        let result = backend.execute(inp).expect("Execution");
+        assert_eq!(result.rule_name.expect("Rule Name").as_str(), "rule_1");
+    }
+    #[test]
+    fn test_future_usage() {
+        let program_str = r#"
+        default: ["stripe", "adyen"]
+
+        rule_1: ["stripe"]
+        {
+           setup_future_usage = off_session
+        }
+        "#;
+
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let inp = inputs::BackendInput {
+            metadata: None,
+            payment: inputs::PaymentInput {
+                amount: 32,
+                currency: enums::Currency::USD,
+                card_bin: None,
+                authentication_type: Some(enums::AuthenticationType::NoThreeDs),
+                capture_method: Some(enums::CaptureMethod::Automatic),
+                business_country: Some(enums::Country::UnitedStatesOfAmerica),
+                billing_country: Some(enums::Country::France),
+                business_label: None,
+                setup_future_usage: Some(enums::SetupFutureUsage::OffSession),
+            },
+            payment_method: inputs::PaymentMethodInput {
+                payment_method: Some(enums::PaymentMethod::PayLater),
+                payment_method_type: Some(enums::PaymentMethodType::Affirm),
+                card_network: None,
+            },
+            mandate: inputs::MandateData {
+                mandate_acceptance_type: None,
+                mandate_type: None,
+                payment_type: None,
+            },
+        };
+
+        let backend = VirInterpreterBackend::<DummyOutput>::with_program(program).expect("Program");
+        let result = backend.execute(inp).expect("Execution");
+        assert_eq!(result.rule_name.expect("Rule Name").as_str(), "rule_1");
+    }
+
+    #[test]
+    fn test_metadata_execution() {
+        let program_str = r#"
+        default: ["stripe"," adyen"]
+
+        rule_1: ["stripe"]
+        {
+        "metadata_key" = "arbitrary meta"
+        }
+        "#;
+        let mut meta_map = FxHashMap::default();
+        meta_map.insert("metadata_key".to_string(), "arbitrary meta".to_string());
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let inp = inputs::BackendInput {
+            metadata: Some(meta_map),
+            payment: inputs::PaymentInput {
+                amount: 32,
+                card_bin: None,
+                currency: enums::Currency::USD,
+                authentication_type: Some(enums::AuthenticationType::NoThreeDs),
+                capture_method: Some(enums::CaptureMethod::Automatic),
+                business_country: Some(enums::Country::UnitedStatesOfAmerica),
+                billing_country: Some(enums::Country::France),
+                business_label: None,
+                setup_future_usage: None,
+            },
+            payment_method: inputs::PaymentMethodInput {
+                payment_method: Some(enums::PaymentMethod::PayLater),
+                payment_method_type: Some(enums::PaymentMethodType::Affirm),
+                card_network: None,
+            },
+            mandate: inputs::MandateData {
+                mandate_acceptance_type: None,
+                mandate_type: None,
+                payment_type: None,
+            },
+        };
+
+        let backend = VirInterpreterBackend::<DummyOutput>::with_program(program).expect("Program");
+        let result = backend.execute(inp).expect("Execution");
+        assert_eq!(result.rule_name.expect("Rule Name").as_str(), "rule_1");
+    }
+
+    #[test]
+    fn test_less_than_operator() {
+        let program_str = r#"
+        default: ["stripe", "adyen"]
+
+        rule_1: ["stripe"]
+        {
+           amount>=123
+        }
+        "#;
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let inp_greater = inputs::BackendInput {
+            metadata: None,
+            payment: inputs::PaymentInput {
+                amount: 150,
+                card_bin: None,
+                currency: enums::Currency::USD,
+                authentication_type: Some(enums::AuthenticationType::NoThreeDs),
+                capture_method: Some(enums::CaptureMethod::Automatic),
+                business_country: Some(enums::Country::UnitedStatesOfAmerica),
+                billing_country: Some(enums::Country::France),
+                business_label: None,
+                setup_future_usage: None,
+            },
+            payment_method: inputs::PaymentMethodInput {
+                payment_method: Some(enums::PaymentMethod::PayLater),
+                payment_method_type: Some(enums::PaymentMethodType::Affirm),
+                card_network: None,
+            },
+            mandate: inputs::MandateData {
+                mandate_acceptance_type: None,
+                mandate_type: None,
+                payment_type: None,
+            },
+        };
+        let mut inp_equal = inp_greater.clone();
+        inp_equal.payment.amount = 123;
+        let backend = VirInterpreterBackend::<DummyOutput>::with_program(program).expect("Program");
+        let result_greater = backend.execute(inp_greater).expect("Execution");
+        let result_equal = backend.execute(inp_equal).expect("Execution");
+        assert_eq!(
+            result_equal.rule_name.expect("Rule Name").as_str(),
+            "rule_1"
+        );
+        assert_eq!(
+            result_greater.rule_name.expect("Rule Name").as_str(),
+            "rule_1"
+        );
+    }
+
+    #[test]
+    fn test_greater_than_operator() {
+        let program_str = r#"
+        default: ["stripe", "adyen"]
+
+        rule_1: ["stripe"]
+        {
+           amount<=123
+        }
+        "#;
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let inp_lower = inputs::BackendInput {
+            metadata: None,
+            payment: inputs::PaymentInput {
+                amount: 120,
+                card_bin: None,
+                currency: enums::Currency::USD,
+                authentication_type: Some(enums::AuthenticationType::NoThreeDs),
+                capture_method: Some(enums::CaptureMethod::Automatic),
+                business_country: Some(enums::Country::UnitedStatesOfAmerica),
+                billing_country: Some(enums::Country::France),
+                business_label: None,
+                setup_future_usage: None,
+            },
+            payment_method: inputs::PaymentMethodInput {
+                payment_method: Some(enums::PaymentMethod::PayLater),
+                payment_method_type: Some(enums::PaymentMethodType::Affirm),
+                card_network: None,
+            },
+            mandate: inputs::MandateData {
+                mandate_acceptance_type: None,
+                mandate_type: None,
+                payment_type: None,
+            },
+        };
+        let mut inp_equal = inp_lower.clone();
+        inp_equal.payment.amount = 123;
+        let backend = VirInterpreterBackend::<DummyOutput>::with_program(program).expect("Program");
+        let result_equal = backend.execute(inp_equal).expect("Execution");
+        let result_lower = backend.execute(inp_lower).expect("Execution");
+        assert_eq!(
+            result_equal.rule_name.expect("Rule Name").as_str(),
+            "rule_1"
+        );
+        assert_eq!(
+            result_lower.rule_name.expect("Rule Name").as_str(),
+            "rule_1"
+        );
+    }
+}
diff --git a/crates/euclid/src/backend/vir_interpreter/types.rs b/crates/euclid/src/backend/vir_interpreter/types.rs
new file mode 100644
index 000000000000..a144cdaafd08
--- /dev/null
+++ b/crates/euclid/src/backend/vir_interpreter/types.rs
@@ -0,0 +1,126 @@
+use rustc_hash::{FxHashMap, FxHashSet};
+
+use crate::{
+    backend::inputs::BackendInput,
+    dssa,
+    types::{self, EuclidKey, EuclidValue, MetadataValue, NumValueRefinement, StrValue},
+};
+
+#[derive(Debug, Clone, serde::Serialize, thiserror::Error)]
+pub enum VirInterpreterError {
+    #[error("Error when lowering the program: {0:?}")]
+    LoweringError(dssa::types::AnalysisError),
+}
+
+pub struct Context {
+    atomic_values: FxHashSet<EuclidValue>,
+    numeric_values: FxHashMap<EuclidKey, EuclidValue>,
+}
+
+impl Context {
+    pub fn check_presence(&self, value: &EuclidValue) -> bool {
+        let key = value.get_key();
+
+        match key.key_type() {
+            types::DataType::MetadataValue => self.atomic_values.contains(value),
+            types::DataType::StrValue => self.atomic_values.contains(value),
+            types::DataType::EnumVariant => self.atomic_values.contains(value),
+            types::DataType::Number => {
+                let ctx_num_value = self
+                    .numeric_values
+                    .get(&key)
+                    .and_then(|value| value.get_num_value());
+
+                value.get_num_value().zip(ctx_num_value).map_or(
+                    false,
+                    |(program_value, ctx_value)| {
+                        let program_num = program_value.number;
+                        let ctx_num = ctx_value.number;
+
+                        match &program_value.refinement {
+                            None => program_num == ctx_num,
+                            Some(NumValueRefinement::NotEqual) => ctx_num != program_num,
+                            Some(NumValueRefinement::GreaterThan) => ctx_num > program_num,
+                            Some(NumValueRefinement::GreaterThanEqual) => ctx_num >= program_num,
+                            Some(NumValueRefinement::LessThanEqual) => ctx_num <= program_num,
+                            Some(NumValueRefinement::LessThan) => ctx_num < program_num,
+                        }
+                    },
+                )
+            }
+        }
+    }
+
+    pub fn from_input(input: BackendInput) -> Self {
+        let payment = input.payment;
+        let payment_method = input.payment_method;
+        let meta_data = input.metadata;
+        let payment_mandate = input.mandate;
+
+        let mut enum_values: FxHashSet<EuclidValue> =
+            FxHashSet::from_iter([EuclidValue::PaymentCurrency(payment.currency)]);
+
+        if let Some(pm) = payment_method.payment_method {
+            enum_values.insert(EuclidValue::PaymentMethod(pm));
+        }
+
+        if let Some(pmt) = payment_method.payment_method_type {
+            enum_values.insert(EuclidValue::PaymentMethodType(pmt));
+        }
+
+        if let Some(met) = meta_data {
+            for (key, value) in met.into_iter() {
+                enum_values.insert(EuclidValue::Metadata(MetadataValue { key, value }));
+            }
+        }
+
+        if let Some(at) = payment.authentication_type {
+            enum_values.insert(EuclidValue::AuthenticationType(at));
+        }
+
+        if let Some(capture_method) = payment.capture_method {
+            enum_values.insert(EuclidValue::CaptureMethod(capture_method));
+        }
+
+        if let Some(country) = payment.business_country {
+            enum_values.insert(EuclidValue::BusinessCountry(country));
+        }
+
+        if let Some(country) = payment.billing_country {
+            enum_values.insert(EuclidValue::BillingCountry(country));
+        }
+        if let Some(card_bin) = payment.card_bin {
+            enum_values.insert(EuclidValue::CardBin(StrValue { value: card_bin }));
+        }
+        if let Some(business_label) = payment.business_label {
+            enum_values.insert(EuclidValue::BusinessLabel(StrValue {
+                value: business_label,
+            }));
+        }
+        if let Some(setup_future_usage) = payment.setup_future_usage {
+            enum_values.insert(EuclidValue::SetupFutureUsage(setup_future_usage));
+        }
+        if let Some(payment_type) = payment_mandate.payment_type {
+            enum_values.insert(EuclidValue::PaymentType(payment_type));
+        }
+        if let Some(mandate_type) = payment_mandate.mandate_type {
+            enum_values.insert(EuclidValue::MandateType(mandate_type));
+        }
+        if let Some(mandate_acceptance_type) = payment_mandate.mandate_acceptance_type {
+            enum_values.insert(EuclidValue::MandateAcceptanceType(mandate_acceptance_type));
+        }
+
+        let numeric_values: FxHashMap<EuclidKey, EuclidValue> = FxHashMap::from_iter([(
+            EuclidKey::PaymentAmount,
+            EuclidValue::PaymentAmount(types::NumValue {
+                number: payment.amount,
+                refinement: None,
+            }),
+        )]);
+
+        Self {
+            atomic_values: enum_values,
+            numeric_values,
+        }
+    }
+}
diff --git a/crates/euclid/src/dssa.rs b/crates/euclid/src/dssa.rs
new file mode 100644
index 000000000000..2f6f35dfb27c
--- /dev/null
+++ b/crates/euclid/src/dssa.rs
@@ -0,0 +1,7 @@
+//! Domain Specific Static Analyzer
+pub mod analyzer;
+pub mod graph;
+pub mod state_machine;
+pub mod truth;
+pub mod types;
+pub mod utils;
diff --git a/crates/euclid/src/dssa/analyzer.rs b/crates/euclid/src/dssa/analyzer.rs
new file mode 100644
index 000000000000..149ed1fd79cd
--- /dev/null
+++ b/crates/euclid/src/dssa/analyzer.rs
@@ -0,0 +1,447 @@
+//! Static Analysis for the Euclid Rule DSL
+//!
+//! Exposes certain functions that can be used to perform static analysis over programs
+//! in the Euclid Rule DSL. These include standard control flow analyses like testing
+//! conflicting assertions, to Domain Specific Analyses making use of the
+//! [`Knowledge Graph Framework`](crate::dssa::graph).
+use rustc_hash::{FxHashMap, FxHashSet};
+
+use super::{graph::Memoization, types::EuclidAnalysable};
+use crate::{
+    dssa::{graph, state_machine, truth, types},
+    frontend::{
+        ast,
+        dir::{self, EuclidDirFilter},
+        vir,
+    },
+    types::{DataType, Metadata},
+};
+
+/// Analyses conflicting assertions on the same key in a conjunctive context.
+///
+/// For example,
+/// ```notrust
+/// payment_method = card && ... && payment_method = bank_debit
+/// ```notrust
+/// This is a condition that will never evaluate to `true` given a single
+/// payment method and needs to be caught in analysis.
+pub fn analyze_conflicting_assertions(
+    keywise_assertions: &FxHashMap<dir::DirKey, FxHashSet<&dir::DirValue>>,
+    assertion_metadata: &FxHashMap<&dir::DirValue, &Metadata>,
+) -> Result<(), types::AnalysisError> {
+    for (key, value_set) in keywise_assertions {
+        if value_set.len() > 1 {
+            let err_type = types::AnalysisErrorType::ConflictingAssertions {
+                key: key.clone(),
+                values: value_set
+                    .iter()
+                    .map(|val| types::ValueData {
+                        value: (*val).clone(),
+                        metadata: assertion_metadata
+                            .get(val)
+                            .map(|meta| (*meta).clone())
+                            .unwrap_or_default(),
+                    })
+                    .collect(),
+            };
+
+            Err(types::AnalysisError {
+                error_type: err_type,
+                metadata: Default::default(),
+            })?;
+        }
+    }
+    Ok(())
+}
+
+/// Analyses exhaustive negations on the same key in a conjunctive context.
+///
+/// For example,
+/// ```notrust
+/// authentication_type /= three_ds && ... && authentication_type /= no_three_ds
+/// ```notrust
+/// This is a condition that will never evaluate to `true` given any authentication_type
+/// since all the possible values authentication_type can take have been negated.
+pub fn analyze_exhaustive_negations(
+    keywise_negations: &FxHashMap<dir::DirKey, FxHashSet<&dir::DirValue>>,
+    keywise_negation_metadata: &FxHashMap<dir::DirKey, Vec<&Metadata>>,
+) -> Result<(), types::AnalysisError> {
+    for (key, negation_set) in keywise_negations {
+        let mut value_set = if let Some(set) = key.kind.get_value_set() {
+            set
+        } else {
+            continue;
+        };
+
+        value_set.retain(|val| !negation_set.contains(val));
+
+        if value_set.is_empty() {
+            let error_type = types::AnalysisErrorType::ExhaustiveNegation {
+                key: key.clone(),
+                metadata: keywise_negation_metadata
+                    .get(key)
+                    .cloned()
+                    .unwrap_or_default()
+                    .iter()
+                    .cloned()
+                    .cloned()
+                    .collect(),
+            };
+
+            Err(types::AnalysisError {
+                error_type,
+                metadata: Default::default(),
+            })?;
+        }
+    }
+    Ok(())
+}
+
+fn analyze_negated_assertions(
+    keywise_assertions: &FxHashMap<dir::DirKey, FxHashSet<&dir::DirValue>>,
+    assertion_metadata: &FxHashMap<&dir::DirValue, &Metadata>,
+    keywise_negations: &FxHashMap<dir::DirKey, FxHashSet<&dir::DirValue>>,
+    negation_metadata: &FxHashMap<&dir::DirValue, &Metadata>,
+) -> Result<(), types::AnalysisError> {
+    for (key, negation_set) in keywise_negations {
+        let assertion_set = if let Some(set) = keywise_assertions.get(key) {
+            set
+        } else {
+            continue;
+        };
+
+        let intersection = negation_set & assertion_set;
+
+        intersection.iter().next().map_or(Ok(()), |val| {
+            let error_type = types::AnalysisErrorType::NegatedAssertion {
+                value: (*val).clone(),
+                assertion_metadata: assertion_metadata
+                    .get(*val)
+                    .cloned()
+                    .cloned()
+                    .unwrap_or_default(),
+                negation_metadata: negation_metadata
+                    .get(*val)
+                    .cloned()
+                    .cloned()
+                    .unwrap_or_default(),
+            };
+
+            Err(types::AnalysisError {
+                error_type,
+                metadata: Default::default(),
+            })
+        })?;
+    }
+    Ok(())
+}
+
+fn perform_condition_analyses(
+    context: &types::ConjunctiveContext<'_>,
+) -> Result<(), types::AnalysisError> {
+    let mut assertion_metadata: FxHashMap<&dir::DirValue, &Metadata> = FxHashMap::default();
+    let mut keywise_assertions: FxHashMap<dir::DirKey, FxHashSet<&dir::DirValue>> =
+        FxHashMap::default();
+    let mut negation_metadata: FxHashMap<&dir::DirValue, &Metadata> = FxHashMap::default();
+    let mut keywise_negation_metadata: FxHashMap<dir::DirKey, Vec<&Metadata>> =
+        FxHashMap::default();
+    let mut keywise_negations: FxHashMap<dir::DirKey, FxHashSet<&dir::DirValue>> =
+        FxHashMap::default();
+
+    for ctx_val in context {
+        let key = if let Some(k) = ctx_val.value.get_key() {
+            k
+        } else {
+            continue;
+        };
+
+        if let dir::DirKeyKind::Connector = key.kind {
+            continue;
+        }
+
+        if !matches!(key.kind.get_type(), DataType::EnumVariant) {
+            continue;
+        }
+
+        match ctx_val.value {
+            types::CtxValueKind::Assertion(val) => {
+                keywise_assertions
+                    .entry(key.clone())
+                    .or_default()
+                    .insert(val);
+
+                assertion_metadata.insert(val, ctx_val.metadata);
+            }
+
+            types::CtxValueKind::Negation(vals) => {
+                let negation_set = keywise_negations.entry(key.clone()).or_default();
+
+                for val in vals {
+                    negation_set.insert(val);
+                    negation_metadata.insert(val, ctx_val.metadata);
+                }
+
+                keywise_negation_metadata
+                    .entry(key.clone())
+                    .or_default()
+                    .push(ctx_val.metadata);
+            }
+        }
+    }
+
+    analyze_conflicting_assertions(&keywise_assertions, &assertion_metadata)?;
+    analyze_exhaustive_negations(&keywise_negations, &keywise_negation_metadata)?;
+    analyze_negated_assertions(
+        &keywise_assertions,
+        &assertion_metadata,
+        &keywise_negations,
+        &negation_metadata,
+    )?;
+
+    Ok(())
+}
+
+fn perform_context_analyses(
+    context: &types::ConjunctiveContext<'_>,
+    knowledge_graph: &graph::KnowledgeGraph<'_>,
+) -> Result<(), types::AnalysisError> {
+    perform_condition_analyses(context)?;
+    let mut memo = Memoization::new();
+    knowledge_graph
+        .perform_context_analysis(context, &mut memo)
+        .map_err(|err| types::AnalysisError {
+            error_type: types::AnalysisErrorType::GraphAnalysis(err, memo),
+            metadata: Default::default(),
+        })?;
+    Ok(())
+}
+
+pub fn analyze<O: EuclidAnalysable + EuclidDirFilter>(
+    program: ast::Program<O>,
+    knowledge_graph: Option<&graph::KnowledgeGraph<'_>>,
+) -> Result<vir::ValuedProgram<O>, types::AnalysisError> {
+    let dir_program = ast::lowering::lower_program(program)?;
+
+    let selection_data = state_machine::make_connector_selection_data(&dir_program);
+    let mut ctx_manager = state_machine::AnalysisContextManager::new(&dir_program, &selection_data);
+    while let Some(ctx) = ctx_manager.advance().map_err(|err| types::AnalysisError {
+        metadata: Default::default(),
+        error_type: types::AnalysisErrorType::StateMachine(err),
+    })? {
+        perform_context_analyses(ctx, knowledge_graph.unwrap_or(&truth::ANALYSIS_GRAPH))?;
+    }
+
+    dir::lowering::lower_program(dir_program)
+}
+
+#[cfg(all(test, feature = "ast_parser"))]
+mod tests {
+    #![allow(clippy::panic, clippy::expect_used)]
+
+    use std::{ops::Deref, sync::Weak};
+
+    use euclid_macros::knowledge;
+
+    use super::*;
+    use crate::{dirval, types::DummyOutput};
+
+    #[test]
+    fn test_conflicting_assertion_detection() {
+        let program_str = r#"
+            default: ["stripe", "adyen"]
+
+            stripe_first: ["stripe", "adyen"]
+            {
+                payment_method = wallet {
+                    amount > 500 & capture_method = automatic
+                    amount < 500 & payment_method = card
+                }
+            }
+        "#;
+
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let analysis_result = analyze(program, None);
+
+        if let Err(types::AnalysisError {
+            error_type: types::AnalysisErrorType::ConflictingAssertions { key, values },
+            ..
+        }) = analysis_result
+        {
+            assert!(
+                matches!(key.kind, dir::DirKeyKind::PaymentMethod),
+                "Key should be payment_method"
+            );
+            let values: Vec<dir::DirValue> = values.into_iter().map(|v| v.value).collect();
+            assert_eq!(values.len(), 2, "There should be 2 conflicting conditions");
+            assert!(
+                values.contains(&dirval!(PaymentMethod = Wallet)),
+                "Condition should include payment_method = wallet"
+            );
+            assert!(
+                values.contains(&dirval!(PaymentMethod = Card)),
+                "Condition should include payment_method = card"
+            );
+        } else {
+            panic!("Did not receive conflicting assertions error");
+        }
+    }
+
+    #[test]
+    fn test_exhaustive_negation_detection() {
+        let program_str = r#"
+            default: ["stripe"]
+
+            rule_1: ["adyen"]
+            {
+                payment_method /= wallet {
+                    capture_method = manual & payment_method /= card {
+                        authentication_type = three_ds & payment_method /= pay_later {
+                            amount > 1000 & payment_method /= bank_redirect {
+                                payment_method /= crypto
+                                    & payment_method /= bank_debit
+                                    & payment_method /= bank_transfer
+                                    & payment_method /= upi
+                                    & payment_method /= reward
+                                    & payment_method /= voucher
+                                    & payment_method /= gift_card
+
+                            }
+                        }
+                    }
+                }
+            }
+        "#;
+
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let analysis_result = analyze(program, None);
+
+        if let Err(types::AnalysisError {
+            error_type: types::AnalysisErrorType::ExhaustiveNegation { key, .. },
+            ..
+        }) = analysis_result
+        {
+            assert!(
+                matches!(key.kind, dir::DirKeyKind::PaymentMethod),
+                "Expected key to be payment_method"
+            );
+        } else {
+            panic!("Expected exhaustive negation error");
+        }
+    }
+
+    #[test]
+    fn test_negated_assertions_detection() {
+        let program_str = r#"
+            default: ["stripe"]
+
+            rule_1: ["adyen"]
+            {
+                payment_method = wallet {
+                    amount > 500 {
+                        capture_method = automatic
+                    }
+
+                    amount < 501 {
+                        payment_method /= wallet
+                    }
+                }
+            }
+        "#;
+
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let analysis_result = analyze(program, None);
+
+        if let Err(types::AnalysisError {
+            error_type: types::AnalysisErrorType::NegatedAssertion { value, .. },
+            ..
+        }) = analysis_result
+        {
+            assert_eq!(
+                value,
+                dirval!(PaymentMethod = Wallet),
+                "Expected to catch payment_method = wallet as conflict"
+            );
+        } else {
+            panic!("Expected negated assertion error");
+        }
+    }
+
+    #[test]
+    fn test_negation_graph_analysis() {
+        let graph = knowledge! {crate
+            CaptureMethod(Automatic) ->> PaymentMethod(Card);
+        };
+
+        let program_str = r#"
+            default: ["stripe"]
+
+            rule_1: ["adyen"]
+            {
+                amount > 500 {
+                    payment_method = pay_later
+                }
+
+                amount < 500 {
+                    payment_method /= wallet & payment_method /= pay_later
+                }
+            }
+        "#;
+
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Graph");
+        let analysis_result = analyze(program, Some(&graph));
+
+        let error_type = match analysis_result {
+            Err(types::AnalysisError { error_type, .. }) => error_type,
+            _ => panic!("Error_type not found"),
+        };
+
+        let a_err = match error_type {
+            types::AnalysisErrorType::GraphAnalysis(trace, memo) => (trace, memo),
+            _ => panic!("Graph Analysis not found"),
+        };
+
+        let (trace, metadata) = match a_err.0 {
+            graph::AnalysisError::NegationTrace { trace, metadata } => (trace, metadata),
+            _ => panic!("Negation Trace not found"),
+        };
+
+        let predecessor = match Weak::upgrade(&trace)
+            .expect("Expected Arc not found")
+            .deref()
+            .clone()
+        {
+            graph::AnalysisTrace::Value { predecessors, .. } => {
+                let _value = graph::NodeValue::Value(dir::DirValue::PaymentMethod(
+                    dir::enums::PaymentMethod::Card,
+                ));
+                let _relation = graph::Relation::Positive;
+                predecessors
+            }
+            _ => panic!("Expected Negation Trace for payment method = card"),
+        };
+
+        let pred = match predecessor {
+            Some(graph::ValueTracePredecessor::Mandatory(predecessor)) => predecessor,
+            _ => panic!("No predecessor found"),
+        };
+        assert_eq!(
+            metadata.len(),
+            2,
+            "Expected two metadats for wallet and pay_later"
+        );
+        assert!(matches!(
+            *Weak::upgrade(&pred)
+                .expect("Expected Arc not found")
+                .deref(),
+            graph::AnalysisTrace::Value {
+                value: graph::NodeValue::Value(dir::DirValue::CaptureMethod(
+                    dir::enums::CaptureMethod::Automatic
+                )),
+                relation: graph::Relation::Positive,
+                info: None,
+                metadata: None,
+                predecessors: None,
+            }
+        ));
+    }
+}
diff --git a/crates/euclid/src/dssa/graph.rs b/crates/euclid/src/dssa/graph.rs
new file mode 100644
index 000000000000..bd23ae385226
--- /dev/null
+++ b/crates/euclid/src/dssa/graph.rs
@@ -0,0 +1,1478 @@
+use std::{
+    fmt::Debug,
+    hash::Hash,
+    ops::{Deref, DerefMut},
+    sync::{Arc, Weak},
+};
+
+use erased_serde::{self, Serialize as ErasedSerialize};
+use rustc_hash::{FxHashMap, FxHashSet};
+use serde::Serialize;
+
+use crate::{
+    dssa::types,
+    frontend::dir,
+    types::{DataType, Metadata},
+    utils,
+};
+
+#[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq, Hash, strum::Display)]
+pub enum Strength {
+    Weak,
+    Normal,
+    Strong,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::Display, Serialize)]
+#[serde(rename_all = "snake_case")]
+pub enum Relation {
+    Positive,
+    Negative,
+}
+
+impl From<Relation> for bool {
+    fn from(value: Relation) -> Self {
+        matches!(value, Relation::Positive)
+    }
+}
+
+#[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq, Hash)]
+pub struct NodeId(usize);
+
+impl utils::EntityId for NodeId {
+    #[inline]
+    fn get_id(&self) -> usize {
+        self.0
+    }
+
+    #[inline]
+    fn with_id(id: usize) -> Self {
+        Self(id)
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct DomainInfo<'a> {
+    pub domain_identifier: DomainIdentifier<'a>,
+    pub domain_description: String,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct DomainIdentifier<'a>(&'a str);
+
+impl<'a> DomainIdentifier<'a> {
+    pub fn new(domain_identifier: &'a str) -> Self {
+        Self(domain_identifier)
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct DomainId(usize);
+
+impl utils::EntityId for DomainId {
+    #[inline]
+    fn get_id(&self) -> usize {
+        self.0
+    }
+
+    #[inline]
+    fn with_id(id: usize) -> Self {
+        Self(id)
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct EdgeId(usize);
+
+impl utils::EntityId for EdgeId {
+    #[inline]
+    fn get_id(&self) -> usize {
+        self.0
+    }
+
+    #[inline]
+    fn with_id(id: usize) -> Self {
+        Self(id)
+    }
+}
+
+#[derive(Debug, Clone, Serialize)]
+pub struct Memoization(FxHashMap<(NodeId, Relation, Strength), Result<(), Arc<AnalysisTrace>>>);
+
+impl Memoization {
+    pub fn new() -> Self {
+        Self(FxHashMap::default())
+    }
+}
+
+impl Default for Memoization {
+    #[inline]
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl Deref for Memoization {
+    type Target = FxHashMap<(NodeId, Relation, Strength), Result<(), Arc<AnalysisTrace>>>;
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+impl DerefMut for Memoization {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+#[derive(Debug, Clone)]
+pub struct Edge {
+    pub strength: Strength,
+    pub relation: Relation,
+    pub pred: NodeId,
+    pub succ: NodeId,
+}
+
+#[derive(Debug)]
+pub struct Node {
+    pub node_type: NodeType,
+    pub preds: Vec<EdgeId>,
+    pub succs: Vec<EdgeId>,
+    pub domain_ids: Vec<DomainId>,
+}
+
+impl Node {
+    fn new(node_type: NodeType, domain_ids: Vec<DomainId>) -> Self {
+        Self {
+            node_type,
+            preds: Vec::new(),
+            succs: Vec::new(),
+            domain_ids,
+        }
+    }
+}
+
+pub trait KgraphMetadata: ErasedSerialize + std::any::Any + Sync + Send + Debug {}
+erased_serde::serialize_trait_object!(KgraphMetadata);
+
+impl<M> KgraphMetadata for M where M: ErasedSerialize + std::any::Any + Sync + Send + Debug {}
+
+#[derive(Debug)]
+pub struct KnowledgeGraph<'a> {
+    domain: utils::DenseMap<DomainId, DomainInfo<'a>>,
+    nodes: utils::DenseMap<NodeId, Node>,
+    edges: utils::DenseMap<EdgeId, Edge>,
+    value_map: FxHashMap<NodeValue, NodeId>,
+    node_info: utils::DenseMap<NodeId, Option<&'static str>>,
+    node_metadata: utils::DenseMap<NodeId, Option<Arc<dyn KgraphMetadata>>>,
+}
+
+pub struct KnowledgeGraphBuilder<'a> {
+    domain: utils::DenseMap<DomainId, DomainInfo<'a>>,
+    nodes: utils::DenseMap<NodeId, Node>,
+    edges: utils::DenseMap<EdgeId, Edge>,
+    domain_identifier_map: FxHashMap<DomainIdentifier<'a>, DomainId>,
+    value_map: FxHashMap<NodeValue, NodeId>,
+    edges_map: FxHashMap<(NodeId, NodeId), EdgeId>,
+    node_info: utils::DenseMap<NodeId, Option<&'static str>>,
+    node_metadata: utils::DenseMap<NodeId, Option<Arc<dyn KgraphMetadata>>>,
+}
+
+impl<'a> Default for KnowledgeGraphBuilder<'a> {
+    #[inline]
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+#[derive(Debug, PartialEq, Eq)]
+pub enum NodeType {
+    AllAggregator,
+    AnyAggregator,
+    InAggregator(FxHashSet<dir::DirValue>),
+    Value(NodeValue),
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize)]
+#[serde(tag = "type", content = "value", rename_all = "snake_case")]
+pub enum NodeValue {
+    Key(dir::DirKey),
+    Value(dir::DirValue),
+}
+
+impl From<dir::DirValue> for NodeValue {
+    fn from(value: dir::DirValue) -> Self {
+        Self::Value(value)
+    }
+}
+
+impl From<dir::DirKey> for NodeValue {
+    fn from(key: dir::DirKey) -> Self {
+        Self::Key(key)
+    }
+}
+
+#[derive(Debug, Clone, serde::Serialize)]
+#[serde(tag = "type", content = "predecessor", rename_all = "snake_case")]
+pub enum ValueTracePredecessor {
+    Mandatory(Box<Weak<AnalysisTrace>>),
+    OneOf(Vec<Weak<AnalysisTrace>>),
+}
+
+#[derive(Debug, Clone, serde::Serialize)]
+#[serde(tag = "type", content = "trace", rename_all = "snake_case")]
+pub enum AnalysisTrace {
+    Value {
+        value: NodeValue,
+        relation: Relation,
+        predecessors: Option<ValueTracePredecessor>,
+        info: Option<&'static str>,
+        metadata: Option<Arc<dyn KgraphMetadata>>,
+    },
+
+    AllAggregation {
+        unsatisfied: Vec<Weak<AnalysisTrace>>,
+        info: Option<&'static str>,
+        metadata: Option<Arc<dyn KgraphMetadata>>,
+    },
+
+    AnyAggregation {
+        unsatisfied: Vec<Weak<AnalysisTrace>>,
+        info: Option<&'static str>,
+        metadata: Option<Arc<dyn KgraphMetadata>>,
+    },
+
+    InAggregation {
+        expected: Vec<dir::DirValue>,
+        found: Option<dir::DirValue>,
+        relation: Relation,
+        info: Option<&'static str>,
+        metadata: Option<Arc<dyn KgraphMetadata>>,
+    },
+}
+
+#[derive(Debug, Clone, serde::Serialize)]
+#[serde(tag = "type", content = "details", rename_all = "snake_case")]
+pub enum AnalysisError {
+    Graph(GraphError),
+    AssertionTrace {
+        trace: Weak<AnalysisTrace>,
+        metadata: Metadata,
+    },
+    NegationTrace {
+        trace: Weak<AnalysisTrace>,
+        metadata: Vec<Metadata>,
+    },
+}
+
+impl AnalysisError {
+    fn assertion_from_graph_error(metadata: &Metadata, graph_error: GraphError) -> Self {
+        match graph_error {
+            GraphError::AnalysisError(trace) => Self::AssertionTrace {
+                trace,
+                metadata: metadata.clone(),
+            },
+
+            other => Self::Graph(other),
+        }
+    }
+
+    fn negation_from_graph_error(metadata: Vec<&Metadata>, graph_error: GraphError) -> Self {
+        match graph_error {
+            GraphError::AnalysisError(trace) => Self::NegationTrace {
+                trace,
+                metadata: metadata.iter().map(|m| (*m).clone()).collect(),
+            },
+
+            other => Self::Graph(other),
+        }
+    }
+}
+
+#[derive(Debug, Clone, serde::Serialize, thiserror::Error)]
+#[serde(tag = "type", content = "info", rename_all = "snake_case")]
+pub enum GraphError {
+    #[error("An edge was not found in the graph")]
+    EdgeNotFound,
+    #[error("Attempted to create a conflicting edge between two nodes")]
+    ConflictingEdgeCreated,
+    #[error("Cycle detected in graph")]
+    CycleDetected,
+    #[error("Domain wasn't found in the Graph")]
+    DomainNotFound,
+    #[error("Malformed Graph: {reason}")]
+    MalformedGraph { reason: String },
+    #[error("A node was not found in the graph")]
+    NodeNotFound,
+    #[error("A value node was not found: {0:#?}")]
+    ValueNodeNotFound(dir::DirValue),
+    #[error("No values provided for an 'in' aggregator node")]
+    NoInAggregatorValues,
+    #[error("Error during analysis: {0:#?}")]
+    AnalysisError(Weak<AnalysisTrace>),
+}
+
+impl GraphError {
+    fn get_analysis_trace(self) -> Result<Weak<AnalysisTrace>, Self> {
+        match self {
+            Self::AnalysisError(trace) => Ok(trace),
+            _ => Err(self),
+        }
+    }
+}
+
+impl PartialEq<dir::DirValue> for NodeValue {
+    fn eq(&self, other: &dir::DirValue) -> bool {
+        match self {
+            Self::Key(dir_key) => *dir_key == other.get_key(),
+            Self::Value(dir_value) if dir_value.get_key() == other.get_key() => {
+                if let (Some(left), Some(right)) =
+                    (dir_value.get_num_value(), other.get_num_value())
+                {
+                    left.fits(&right)
+                } else {
+                    dir::DirValue::check_equality(dir_value, other)
+                }
+            }
+            Self::Value(_) => false,
+        }
+    }
+}
+
+pub struct AnalysisContext {
+    keywise_values: FxHashMap<dir::DirKey, FxHashSet<dir::DirValue>>,
+}
+
+impl AnalysisContext {
+    pub fn from_dir_values(vals: impl IntoIterator<Item = dir::DirValue>) -> Self {
+        let mut keywise_values: FxHashMap<dir::DirKey, FxHashSet<dir::DirValue>> =
+            FxHashMap::default();
+
+        for dir_val in vals {
+            let key = dir_val.get_key();
+            let set = keywise_values.entry(key).or_default();
+            set.insert(dir_val);
+        }
+
+        Self { keywise_values }
+    }
+
+    fn check_presence(&self, value: &NodeValue, weak: bool) -> bool {
+        match value {
+            NodeValue::Key(k) => self.keywise_values.contains_key(k) || weak,
+            NodeValue::Value(val) => {
+                let key = val.get_key();
+                let value_set = if let Some(set) = self.keywise_values.get(&key) {
+                    set
+                } else {
+                    return weak;
+                };
+
+                match key.kind.get_type() {
+                    DataType::EnumVariant | DataType::StrValue | DataType::MetadataValue => {
+                        value_set.contains(val)
+                    }
+                    DataType::Number => val.get_num_value().map_or(false, |num_val| {
+                        value_set.iter().any(|ctx_val| {
+                            ctx_val
+                                .get_num_value()
+                                .map_or(false, |ctx_num_val| num_val.fits(&ctx_num_val))
+                        })
+                    }),
+                }
+            }
+        }
+    }
+
+    pub fn insert(&mut self, value: dir::DirValue) {
+        self.keywise_values
+            .entry(value.get_key())
+            .or_default()
+            .insert(value);
+    }
+
+    pub fn remove(&mut self, value: dir::DirValue) {
+        let set = self.keywise_values.entry(value.get_key()).or_default();
+
+        set.remove(&value);
+
+        if set.is_empty() {
+            self.keywise_values.remove(&value.get_key());
+        }
+    }
+}
+
+impl<'a> KnowledgeGraphBuilder<'a> {
+    pub fn new() -> Self {
+        Self {
+            domain: utils::DenseMap::new(),
+            nodes: utils::DenseMap::new(),
+            edges: utils::DenseMap::new(),
+            domain_identifier_map: FxHashMap::default(),
+            value_map: FxHashMap::default(),
+            edges_map: FxHashMap::default(),
+            node_info: utils::DenseMap::new(),
+            node_metadata: utils::DenseMap::new(),
+        }
+    }
+
+    pub fn build(self) -> KnowledgeGraph<'a> {
+        KnowledgeGraph {
+            domain: self.domain,
+            nodes: self.nodes,
+            edges: self.edges,
+            value_map: self.value_map,
+            node_info: self.node_info,
+            node_metadata: self.node_metadata,
+        }
+    }
+
+    pub fn make_domain(
+        &mut self,
+        domain_identifier: DomainIdentifier<'a>,
+        domain_description: String,
+    ) -> Result<DomainId, GraphError> {
+        Ok(self
+            .domain_identifier_map
+            .clone()
+            .get(&domain_identifier)
+            .map_or_else(
+                || {
+                    let domain_id = self.domain.push(DomainInfo {
+                        domain_identifier: domain_identifier.clone(),
+                        domain_description,
+                    });
+                    self.domain_identifier_map
+                        .insert(domain_identifier.clone(), domain_id);
+                    domain_id
+                },
+                |domain_id| *domain_id,
+            ))
+    }
+
+    pub fn make_value_node<M: KgraphMetadata>(
+        &mut self,
+        value: NodeValue,
+        info: Option<&'static str>,
+        domain_identifiers: Vec<DomainIdentifier<'_>>,
+        metadata: Option<M>,
+    ) -> Result<NodeId, GraphError> {
+        match self.value_map.get(&value).copied() {
+            Some(node_id) => Ok(node_id),
+            None => {
+                let mut domain_ids: Vec<DomainId> = Vec::new();
+                domain_identifiers
+                    .iter()
+                    .try_for_each(|ident| {
+                        self.domain_identifier_map
+                            .get(ident)
+                            .map(|id| domain_ids.push(*id))
+                    })
+                    .ok_or(GraphError::DomainNotFound)?;
+
+                let node_id = self
+                    .nodes
+                    .push(Node::new(NodeType::Value(value.clone()), domain_ids));
+                let _node_info_id = self.node_info.push(info);
+
+                let _node_metadata_id = self
+                    .node_metadata
+                    .push(metadata.map(|meta| -> Arc<dyn KgraphMetadata> { Arc::new(meta) }));
+
+                self.value_map.insert(value, node_id);
+                Ok(node_id)
+            }
+        }
+    }
+
+    pub fn make_edge(
+        &mut self,
+        pred_id: NodeId,
+        succ_id: NodeId,
+        strength: Strength,
+        relation: Relation,
+    ) -> Result<EdgeId, GraphError> {
+        self.ensure_node_exists(pred_id)?;
+        self.ensure_node_exists(succ_id)?;
+        self.edges_map
+            .get(&(pred_id, succ_id))
+            .copied()
+            .and_then(|edge_id| self.edges.get(edge_id).cloned().map(|edge| (edge_id, edge)))
+            .map_or_else(
+                || {
+                    let edge_id = self.edges.push(Edge {
+                        strength,
+                        relation,
+                        pred: pred_id,
+                        succ: succ_id,
+                    });
+                    self.edges_map.insert((pred_id, succ_id), edge_id);
+
+                    let pred = self
+                        .nodes
+                        .get_mut(pred_id)
+                        .ok_or(GraphError::NodeNotFound)?;
+                    pred.succs.push(edge_id);
+
+                    let succ = self
+                        .nodes
+                        .get_mut(succ_id)
+                        .ok_or(GraphError::NodeNotFound)?;
+                    succ.preds.push(edge_id);
+
+                    Ok(edge_id)
+                },
+                |(edge_id, edge)| {
+                    if edge.strength == strength && edge.relation == relation {
+                        Ok(edge_id)
+                    } else {
+                        Err(GraphError::ConflictingEdgeCreated)
+                    }
+                },
+            )
+    }
+
+    pub fn make_all_aggregator<M: KgraphMetadata>(
+        &mut self,
+        nodes: &[(NodeId, Relation, Strength)],
+        info: Option<&'static str>,
+        metadata: Option<M>,
+        domain: Vec<DomainIdentifier<'_>>,
+    ) -> Result<NodeId, GraphError> {
+        nodes
+            .iter()
+            .try_for_each(|(node_id, _, _)| self.ensure_node_exists(*node_id))?;
+
+        let mut domain_ids: Vec<DomainId> = Vec::new();
+        domain
+            .iter()
+            .try_for_each(|ident| {
+                self.domain_identifier_map
+                    .get(ident)
+                    .map(|id| domain_ids.push(*id))
+            })
+            .ok_or(GraphError::DomainNotFound)?;
+
+        let aggregator_id = self
+            .nodes
+            .push(Node::new(NodeType::AllAggregator, domain_ids));
+        let _aggregator_info_id = self.node_info.push(info);
+
+        let _node_metadata_id = self
+            .node_metadata
+            .push(metadata.map(|meta| -> Arc<dyn KgraphMetadata> { Arc::new(meta) }));
+
+        for (node_id, relation, strength) in nodes {
+            self.make_edge(*node_id, aggregator_id, *strength, *relation)?;
+        }
+
+        Ok(aggregator_id)
+    }
+
+    pub fn make_any_aggregator<M: KgraphMetadata>(
+        &mut self,
+        nodes: &[(NodeId, Relation)],
+        info: Option<&'static str>,
+        metadata: Option<M>,
+        domain: Vec<DomainIdentifier<'_>>,
+    ) -> Result<NodeId, GraphError> {
+        nodes
+            .iter()
+            .try_for_each(|(node_id, _)| self.ensure_node_exists(*node_id))?;
+
+        let mut domain_ids: Vec<DomainId> = Vec::new();
+        domain
+            .iter()
+            .try_for_each(|ident| {
+                self.domain_identifier_map
+                    .get(ident)
+                    .map(|id| domain_ids.push(*id))
+            })
+            .ok_or(GraphError::DomainNotFound)?;
+
+        let aggregator_id = self
+            .nodes
+            .push(Node::new(NodeType::AnyAggregator, domain_ids));
+        let _aggregator_info_id = self.node_info.push(info);
+
+        let _node_metadata_id = self
+            .node_metadata
+            .push(metadata.map(|meta| -> Arc<dyn KgraphMetadata> { Arc::new(meta) }));
+
+        for (node_id, relation) in nodes {
+            self.make_edge(*node_id, aggregator_id, Strength::Strong, *relation)?;
+        }
+
+        Ok(aggregator_id)
+    }
+
+    pub fn make_in_aggregator<M: KgraphMetadata>(
+        &mut self,
+        values: Vec<dir::DirValue>,
+        info: Option<&'static str>,
+        metadata: Option<M>,
+        domain: Vec<DomainIdentifier<'_>>,
+    ) -> Result<NodeId, GraphError> {
+        let key = values
+            .first()
+            .ok_or(GraphError::NoInAggregatorValues)?
+            .get_key();
+
+        for val in &values {
+            if val.get_key() != key {
+                Err(GraphError::MalformedGraph {
+                    reason: "Values for 'In' aggregator not of same key".to_string(),
+                })?;
+            }
+        }
+
+        let mut domain_ids: Vec<DomainId> = Vec::new();
+        domain
+            .iter()
+            .try_for_each(|ident| {
+                self.domain_identifier_map
+                    .get(ident)
+                    .map(|id| domain_ids.push(*id))
+            })
+            .ok_or(GraphError::DomainNotFound)?;
+
+        let node_id = self.nodes.push(Node::new(
+            NodeType::InAggregator(FxHashSet::from_iter(values)),
+            domain_ids,
+        ));
+        let _aggregator_info_id = self.node_info.push(info);
+
+        let _node_metadata_id = self
+            .node_metadata
+            .push(metadata.map(|meta| -> Arc<dyn KgraphMetadata> { Arc::new(meta) }));
+
+        Ok(node_id)
+    }
+
+    fn ensure_node_exists(&self, id: NodeId) -> Result<(), GraphError> {
+        if self.nodes.contains_key(id) {
+            Ok(())
+        } else {
+            Err(GraphError::NodeNotFound)
+        }
+    }
+}
+
+impl<'a> KnowledgeGraph<'a> {
+    fn check_node(
+        &self,
+        ctx: &AnalysisContext,
+        node_id: NodeId,
+        relation: Relation,
+        strength: Strength,
+        memo: &mut Memoization,
+    ) -> Result<(), GraphError> {
+        let node = self.nodes.get(node_id).ok_or(GraphError::NodeNotFound)?;
+        if let Some(already_memo) = memo.get(&(node_id, relation, strength)) {
+            already_memo
+                .clone()
+                .map_err(|err| GraphError::AnalysisError(Arc::downgrade(&err)))
+        } else {
+            match &node.node_type {
+                NodeType::AllAggregator => {
+                    let mut unsatisfied = Vec::<Weak<AnalysisTrace>>::new();
+
+                    for edge_id in node.preds.iter().copied() {
+                        let edge = self.edges.get(edge_id).ok_or(GraphError::EdgeNotFound)?;
+
+                        if let Err(e) =
+                            self.check_node(ctx, edge.pred, edge.relation, edge.strength, memo)
+                        {
+                            unsatisfied.push(e.get_analysis_trace()?);
+                        }
+                    }
+
+                    if !unsatisfied.is_empty() {
+                        let err = Arc::new(AnalysisTrace::AllAggregation {
+                            unsatisfied,
+                            info: self.node_info.get(node_id).cloned().flatten(),
+                            metadata: self.node_metadata.get(node_id).cloned().flatten(),
+                        });
+
+                        memo.insert((node_id, relation, strength), Err(Arc::clone(&err)));
+                        Err(GraphError::AnalysisError(Arc::downgrade(&err)))
+                    } else {
+                        memo.insert((node_id, relation, strength), Ok(()));
+                        Ok(())
+                    }
+                }
+
+                NodeType::AnyAggregator => {
+                    let mut unsatisfied = Vec::<Weak<AnalysisTrace>>::new();
+                    let mut matched_one = false;
+
+                    for edge_id in node.preds.iter().copied() {
+                        let edge = self.edges.get(edge_id).ok_or(GraphError::EdgeNotFound)?;
+
+                        if let Err(e) =
+                            self.check_node(ctx, edge.pred, edge.relation, edge.strength, memo)
+                        {
+                            unsatisfied.push(e.get_analysis_trace()?);
+                        } else {
+                            matched_one = true;
+                        }
+                    }
+
+                    if matched_one || node.preds.is_empty() {
+                        memo.insert((node_id, relation, strength), Ok(()));
+                        Ok(())
+                    } else {
+                        let err = Arc::new(AnalysisTrace::AnyAggregation {
+                            unsatisfied: unsatisfied.clone(),
+                            info: self.node_info.get(node_id).cloned().flatten(),
+                            metadata: self.node_metadata.get(node_id).cloned().flatten(),
+                        });
+
+                        memo.insert((node_id, relation, strength), Err(Arc::clone(&err)));
+                        Err(GraphError::AnalysisError(Arc::downgrade(&err)))
+                    }
+                }
+
+                NodeType::InAggregator(expected) => {
+                    let the_key = expected
+                        .iter()
+                        .next()
+                        .ok_or_else(|| GraphError::MalformedGraph {
+                            reason:
+                                "An OnlyIn aggregator node must have at least one expected value"
+                                    .to_string(),
+                        })?
+                        .get_key();
+
+                    let ctx_vals = if let Some(vals) = ctx.keywise_values.get(&the_key) {
+                        vals
+                    } else {
+                        return if let Strength::Weak = strength {
+                            memo.insert((node_id, relation, strength), Ok(()));
+                            Ok(())
+                        } else {
+                            let err = Arc::new(AnalysisTrace::InAggregation {
+                                expected: expected.iter().cloned().collect(),
+                                found: None,
+                                relation,
+                                info: self.node_info.get(node_id).cloned().flatten(),
+                                metadata: self.node_metadata.get(node_id).cloned().flatten(),
+                            });
+
+                            memo.insert((node_id, relation, strength), Err(Arc::clone(&err)));
+                            Err(GraphError::AnalysisError(Arc::downgrade(&err)))
+                        };
+                    };
+
+                    let relation_bool: bool = relation.into();
+                    for ctx_value in ctx_vals {
+                        if expected.contains(ctx_value) != relation_bool {
+                            let err = Arc::new(AnalysisTrace::InAggregation {
+                                expected: expected.iter().cloned().collect(),
+                                found: Some(ctx_value.clone()),
+                                relation,
+                                info: self.node_info.get(node_id).cloned().flatten(),
+                                metadata: self.node_metadata.get(node_id).cloned().flatten(),
+                            });
+
+                            memo.insert((node_id, relation, strength), Err(Arc::clone(&err)));
+                            Err(GraphError::AnalysisError(Arc::downgrade(&err)))?;
+                        }
+                    }
+
+                    memo.insert((node_id, relation, strength), Ok(()));
+                    Ok(())
+                }
+
+                NodeType::Value(val) => {
+                    let in_context = ctx.check_presence(val, matches!(strength, Strength::Weak));
+                    let relation_bool: bool = relation.into();
+
+                    if in_context != relation_bool {
+                        let err = Arc::new(AnalysisTrace::Value {
+                            value: val.clone(),
+                            relation,
+                            predecessors: None,
+                            info: self.node_info.get(node_id).cloned().flatten(),
+                            metadata: self.node_metadata.get(node_id).cloned().flatten(),
+                        });
+
+                        memo.insert((node_id, relation, strength), Err(Arc::clone(&err)));
+                        Err(GraphError::AnalysisError(Arc::downgrade(&err)))?;
+                    }
+
+                    if !relation_bool {
+                        memo.insert((node_id, relation, strength), Ok(()));
+                        return Ok(());
+                    }
+
+                    let mut errors = Vec::<Weak<AnalysisTrace>>::new();
+                    let mut matched_one = false;
+
+                    for edge_id in node.preds.iter().copied() {
+                        let edge = self.edges.get(edge_id).ok_or(GraphError::EdgeNotFound)?;
+                        let result =
+                            self.check_node(ctx, edge.pred, edge.relation, edge.strength, memo);
+
+                        match (edge.strength, result) {
+                            (Strength::Strong, Err(trace)) => {
+                                let err = Arc::new(AnalysisTrace::Value {
+                                    value: val.clone(),
+                                    relation,
+                                    info: self.node_info.get(node_id).cloned().flatten(),
+                                    metadata: self.node_metadata.get(node_id).cloned().flatten(),
+                                    predecessors: Some(ValueTracePredecessor::Mandatory(Box::new(
+                                        trace.get_analysis_trace()?,
+                                    ))),
+                                });
+                                memo.insert((node_id, relation, strength), Err(Arc::clone(&err)));
+                                Err(GraphError::AnalysisError(Arc::downgrade(&err)))?;
+                            }
+
+                            (Strength::Strong, Ok(_)) => {
+                                matched_one = true;
+                            }
+
+                            (Strength::Normal | Strength::Weak, Err(trace)) => {
+                                errors.push(trace.get_analysis_trace()?);
+                            }
+
+                            (Strength::Normal | Strength::Weak, Ok(_)) => {
+                                matched_one = true;
+                            }
+                        }
+                    }
+
+                    if matched_one || node.preds.is_empty() {
+                        memo.insert((node_id, relation, strength), Ok(()));
+                        Ok(())
+                    } else {
+                        let err = Arc::new(AnalysisTrace::Value {
+                            value: val.clone(),
+                            relation,
+                            info: self.node_info.get(node_id).cloned().flatten(),
+                            metadata: self.node_metadata.get(node_id).cloned().flatten(),
+                            predecessors: Some(ValueTracePredecessor::OneOf(errors.clone())),
+                        });
+
+                        memo.insert((node_id, relation, strength), Err(Arc::clone(&err)));
+                        Err(GraphError::AnalysisError(Arc::downgrade(&err)))
+                    }
+                }
+            }
+        }
+    }
+
+    fn key_analysis(
+        &self,
+        key: dir::DirKey,
+        ctx: &AnalysisContext,
+        memo: &mut Memoization,
+    ) -> Result<(), GraphError> {
+        self.value_map
+            .get(&NodeValue::Key(key))
+            .map_or(Ok(()), |node_id| {
+                self.check_node(ctx, *node_id, Relation::Positive, Strength::Strong, memo)
+            })
+    }
+
+    fn value_analysis(
+        &self,
+        val: dir::DirValue,
+        ctx: &AnalysisContext,
+        memo: &mut Memoization,
+    ) -> Result<(), GraphError> {
+        self.value_map
+            .get(&NodeValue::Value(val))
+            .map_or(Ok(()), |node_id| {
+                self.check_node(ctx, *node_id, Relation::Positive, Strength::Strong, memo)
+            })
+    }
+
+    pub fn check_value_validity(
+        &self,
+        val: dir::DirValue,
+        analysis_ctx: &AnalysisContext,
+        memo: &mut Memoization,
+    ) -> Result<bool, GraphError> {
+        let maybe_node_id = self.value_map.get(&NodeValue::Value(val));
+
+        let node_id = if let Some(nid) = maybe_node_id {
+            nid
+        } else {
+            return Ok(false);
+        };
+
+        let result = self.check_node(
+            analysis_ctx,
+            *node_id,
+            Relation::Positive,
+            Strength::Weak,
+            memo,
+        );
+
+        match result {
+            Ok(_) => Ok(true),
+            Err(e) => {
+                e.get_analysis_trace()?;
+                Ok(false)
+            }
+        }
+    }
+
+    pub fn key_value_analysis(
+        &self,
+        val: dir::DirValue,
+        ctx: &AnalysisContext,
+        memo: &mut Memoization,
+    ) -> Result<(), GraphError> {
+        self.key_analysis(val.get_key(), ctx, memo)
+            .and_then(|_| self.value_analysis(val, ctx, memo))
+    }
+
+    fn assertion_analysis(
+        &self,
+        positive_ctx: &[(&dir::DirValue, &Metadata)],
+        analysis_ctx: &AnalysisContext,
+        memo: &mut Memoization,
+    ) -> Result<(), AnalysisError> {
+        positive_ctx.iter().try_for_each(|(value, metadata)| {
+            self.key_value_analysis((*value).clone(), analysis_ctx, memo)
+                .map_err(|e| AnalysisError::assertion_from_graph_error(metadata, e))
+        })
+    }
+
+    fn negation_analysis(
+        &self,
+        negative_ctx: &[(&[dir::DirValue], &Metadata)],
+        analysis_ctx: &mut AnalysisContext,
+        memo: &mut Memoization,
+    ) -> Result<(), AnalysisError> {
+        let mut keywise_metadata: FxHashMap<dir::DirKey, Vec<&Metadata>> = FxHashMap::default();
+        let mut keywise_negation: FxHashMap<dir::DirKey, FxHashSet<&dir::DirValue>> =
+            FxHashMap::default();
+
+        for (values, metadata) in negative_ctx {
+            let mut metadata_added = false;
+
+            for dir_value in *values {
+                if !metadata_added {
+                    keywise_metadata
+                        .entry(dir_value.get_key())
+                        .or_default()
+                        .push(metadata);
+
+                    metadata_added = true;
+                }
+
+                keywise_negation
+                    .entry(dir_value.get_key())
+                    .or_default()
+                    .insert(dir_value);
+            }
+        }
+
+        for (key, negation_set) in keywise_negation {
+            let all_metadata = keywise_metadata.remove(&key).unwrap_or_default();
+            let first_metadata = all_metadata.first().cloned().cloned().unwrap_or_default();
+
+            self.key_analysis(key.clone(), analysis_ctx, memo)
+                .map_err(|e| AnalysisError::assertion_from_graph_error(&first_metadata, e))?;
+
+            let mut value_set = if let Some(set) = key.kind.get_value_set() {
+                set
+            } else {
+                continue;
+            };
+
+            value_set.retain(|v| !negation_set.contains(v));
+
+            for value in value_set {
+                analysis_ctx.insert(value.clone());
+                self.value_analysis(value.clone(), analysis_ctx, memo)
+                    .map_err(|e| {
+                        AnalysisError::negation_from_graph_error(all_metadata.clone(), e)
+                    })?;
+                analysis_ctx.remove(value);
+            }
+        }
+
+        Ok(())
+    }
+
+    pub fn perform_context_analysis(
+        &self,
+        ctx: &types::ConjunctiveContext<'_>,
+        memo: &mut Memoization,
+    ) -> Result<(), AnalysisError> {
+        let mut analysis_ctx = AnalysisContext::from_dir_values(
+            ctx.iter()
+                .filter_map(|ctx_val| ctx_val.value.get_assertion().cloned()),
+        );
+
+        let positive_ctx = ctx
+            .iter()
+            .filter_map(|ctx_val| {
+                ctx_val
+                    .value
+                    .get_assertion()
+                    .map(|val| (val, ctx_val.metadata))
+            })
+            .collect::<Vec<_>>();
+        self.assertion_analysis(&positive_ctx, &analysis_ctx, memo)?;
+
+        let negative_ctx = ctx
+            .iter()
+            .filter_map(|ctx_val| {
+                ctx_val
+                    .value
+                    .get_negation()
+                    .map(|vals| (vals, ctx_val.metadata))
+            })
+            .collect::<Vec<_>>();
+        self.negation_analysis(&negative_ctx, &mut analysis_ctx, memo)?;
+
+        Ok(())
+    }
+
+    pub fn combine<'b>(g1: &'b Self, g2: &'b Self) -> Result<Self, GraphError> {
+        let mut node_builder = KnowledgeGraphBuilder::new();
+        let mut g1_old2new_id = utils::DenseMap::<NodeId, NodeId>::new();
+        let mut g2_old2new_id = utils::DenseMap::<NodeId, NodeId>::new();
+        let mut g1_old2new_domain_id = utils::DenseMap::<DomainId, DomainId>::new();
+        let mut g2_old2new_domain_id = utils::DenseMap::<DomainId, DomainId>::new();
+
+        let add_domain = |node_builder: &mut KnowledgeGraphBuilder<'a>,
+                          domain: DomainInfo<'a>|
+         -> Result<DomainId, GraphError> {
+            node_builder.make_domain(domain.domain_identifier, domain.domain_description)
+        };
+
+        let add_node = |node_builder: &mut KnowledgeGraphBuilder<'a>,
+                        node: &Node,
+                        domains: Vec<DomainIdentifier<'_>>|
+         -> Result<NodeId, GraphError> {
+            match &node.node_type {
+                NodeType::Value(node_value) => {
+                    node_builder.make_value_node(node_value.clone(), None, domains, None::<()>)
+                }
+
+                NodeType::AllAggregator => {
+                    Ok(node_builder.make_all_aggregator(&[], None, None::<()>, domains)?)
+                }
+
+                NodeType::AnyAggregator => {
+                    Ok(node_builder.make_any_aggregator(&[], None, None::<()>, Vec::new())?)
+                }
+
+                NodeType::InAggregator(expected) => Ok(node_builder.make_in_aggregator(
+                    expected.iter().cloned().collect(),
+                    None,
+                    None::<()>,
+                    Vec::new(),
+                )?),
+            }
+        };
+
+        for (_old_domain_id, domain) in g1.domain.iter() {
+            let new_domain_id = add_domain(&mut node_builder, domain.clone())?;
+            g1_old2new_domain_id.push(new_domain_id);
+        }
+
+        for (_old_domain_id, domain) in g2.domain.iter() {
+            let new_domain_id = add_domain(&mut node_builder, domain.clone())?;
+            g2_old2new_domain_id.push(new_domain_id);
+        }
+
+        for (_old_node_id, node) in g1.nodes.iter() {
+            let mut domain_identifiers: Vec<DomainIdentifier<'_>> = Vec::new();
+            for domain_id in &node.domain_ids {
+                match g1.domain.get(*domain_id) {
+                    Some(domain) => domain_identifiers.push(domain.domain_identifier.clone()),
+                    None => return Err(GraphError::DomainNotFound),
+                }
+            }
+            let new_node_id = add_node(&mut node_builder, node, domain_identifiers.clone())?;
+            g1_old2new_id.push(new_node_id);
+        }
+
+        for (_old_node_id, node) in g2.nodes.iter() {
+            let mut domain_identifiers: Vec<DomainIdentifier<'_>> = Vec::new();
+            for domain_id in &node.domain_ids {
+                match g2.domain.get(*domain_id) {
+                    Some(domain) => domain_identifiers.push(domain.domain_identifier.clone()),
+                    None => return Err(GraphError::DomainNotFound),
+                }
+            }
+            let new_node_id = add_node(&mut node_builder, node, domain_identifiers.clone())?;
+            g2_old2new_id.push(new_node_id);
+        }
+
+        for edge in g1.edges.values() {
+            let new_pred_id = g1_old2new_id
+                .get(edge.pred)
+                .ok_or(GraphError::NodeNotFound)?;
+            let new_succ_id = g1_old2new_id
+                .get(edge.succ)
+                .ok_or(GraphError::NodeNotFound)?;
+
+            node_builder.make_edge(*new_pred_id, *new_succ_id, edge.strength, edge.relation)?;
+        }
+
+        for edge in g2.edges.values() {
+            let new_pred_id = g2_old2new_id
+                .get(edge.pred)
+                .ok_or(GraphError::NodeNotFound)?;
+            let new_succ_id = g2_old2new_id
+                .get(edge.succ)
+                .ok_or(GraphError::NodeNotFound)?;
+
+            node_builder.make_edge(*new_pred_id, *new_succ_id, edge.strength, edge.relation)?;
+        }
+
+        Ok(node_builder.build())
+    }
+}
+
+#[cfg(test)]
+mod test {
+    #![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
+
+    use euclid_macros::knowledge;
+
+    use super::*;
+    use crate::{dirval, frontend::dir::enums};
+
+    #[test]
+    fn test_strong_positive_relation_success() {
+        let graph = knowledge! {crate
+            PaymentMethod(Card) ->> CaptureMethod(Automatic);
+            PaymentMethod(not Wallet)
+                & PaymentMethod(not PayLater) -> CaptureMethod(Automatic);
+        };
+        let memo = &mut Memoization::new();
+        let result = graph.key_value_analysis(
+            dirval!(CaptureMethod = Automatic),
+            &AnalysisContext::from_dir_values([
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentMethod = Card),
+            ]),
+            memo,
+        );
+
+        assert!(result.is_ok());
+    }
+
+    #[test]
+    fn test_strong_positive_relation_failure() {
+        let graph = knowledge! {crate
+            PaymentMethod(Card) ->> CaptureMethod(Automatic);
+            PaymentMethod(not Wallet) -> CaptureMethod(Automatic);
+        };
+        let memo = &mut Memoization::new();
+        let result = graph.key_value_analysis(
+            dirval!(CaptureMethod = Automatic),
+            &AnalysisContext::from_dir_values([dirval!(CaptureMethod = Automatic)]),
+            memo,
+        );
+
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_strong_negative_relation_success() {
+        let graph = knowledge! {crate
+            PaymentMethod(Card) -> CaptureMethod(Automatic);
+            PaymentMethod(not Wallet) ->> CaptureMethod(Automatic);
+        };
+        let memo = &mut Memoization::new();
+        let result = graph.key_value_analysis(
+            dirval!(CaptureMethod = Automatic),
+            &AnalysisContext::from_dir_values([
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentMethod = Card),
+            ]),
+            memo,
+        );
+
+        assert!(result.is_ok());
+    }
+
+    #[test]
+    fn test_strong_negative_relation_failure() {
+        let graph = knowledge! {crate
+            PaymentMethod(Card) -> CaptureMethod(Automatic);
+            PaymentMethod(not Wallet) ->> CaptureMethod(Automatic);
+        };
+        let memo = &mut Memoization::new();
+        let result = graph.key_value_analysis(
+            dirval!(CaptureMethod = Automatic),
+            &AnalysisContext::from_dir_values([
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentMethod = Wallet),
+            ]),
+            memo,
+        );
+
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_normal_one_of_failure() {
+        let graph = knowledge! {crate
+            PaymentMethod(Card) -> CaptureMethod(Automatic);
+            PaymentMethod(Wallet) -> CaptureMethod(Automatic);
+        };
+        let memo = &mut Memoization::new();
+        let result = graph.key_value_analysis(
+            dirval!(CaptureMethod = Automatic),
+            &AnalysisContext::from_dir_values([
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentMethod = PayLater),
+            ]),
+            memo,
+        );
+        assert!(matches!(
+            *Weak::upgrade(&result.unwrap_err().get_analysis_trace().unwrap())
+                .expect("Expected Arc"),
+            AnalysisTrace::Value {
+                predecessors: Some(ValueTracePredecessor::OneOf(_)),
+                ..
+            }
+        ));
+    }
+
+    #[test]
+    fn test_all_aggregator_success() {
+        let graph = knowledge! {crate
+            PaymentMethod(Card) & PaymentMethod(not Wallet) -> CaptureMethod(Automatic);
+        };
+        let memo = &mut Memoization::new();
+        let result = graph.key_value_analysis(
+            dirval!(CaptureMethod = Automatic),
+            &AnalysisContext::from_dir_values([
+                dirval!(PaymentMethod = Card),
+                dirval!(CaptureMethod = Automatic),
+            ]),
+            memo,
+        );
+
+        assert!(result.is_ok());
+    }
+
+    #[test]
+    fn test_all_aggregator_failure() {
+        let graph = knowledge! {crate
+            PaymentMethod(Card) & PaymentMethod(not Wallet) -> CaptureMethod(Automatic);
+        };
+        let memo = &mut Memoization::new();
+        let result = graph.key_value_analysis(
+            dirval!(CaptureMethod = Automatic),
+            &AnalysisContext::from_dir_values([
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentMethod = PayLater),
+            ]),
+            memo,
+        );
+
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_all_aggregator_mandatory_failure() {
+        let graph = knowledge! {crate
+            PaymentMethod(Card) & PaymentMethod(not Wallet) ->> CaptureMethod(Automatic);
+        };
+        let mut memo = Memoization::new();
+        let result = graph.key_value_analysis(
+            dirval!(CaptureMethod = Automatic),
+            &AnalysisContext::from_dir_values([
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentMethod = PayLater),
+            ]),
+            &mut memo,
+        );
+
+        assert!(matches!(
+            *Weak::upgrade(&result.unwrap_err().get_analysis_trace().unwrap())
+                .expect("Expected Arc"),
+            AnalysisTrace::Value {
+                predecessors: Some(ValueTracePredecessor::Mandatory(_)),
+                ..
+            }
+        ));
+    }
+
+    #[test]
+    fn test_in_aggregator_success() {
+        let graph = knowledge! {crate
+            PaymentMethod(in [Card, Wallet]) -> CaptureMethod(Automatic);
+        };
+        let memo = &mut Memoization::new();
+        let result = graph.key_value_analysis(
+            dirval!(CaptureMethod = Automatic),
+            &AnalysisContext::from_dir_values([
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentMethod = Card),
+                dirval!(PaymentMethod = Wallet),
+            ]),
+            memo,
+        );
+
+        assert!(result.is_ok());
+    }
+
+    #[test]
+    fn test_in_aggregator_failure() {
+        let graph = knowledge! {crate
+            PaymentMethod(in [Card, Wallet]) -> CaptureMethod(Automatic);
+        };
+        let memo = &mut Memoization::new();
+        let result = graph.key_value_analysis(
+            dirval!(CaptureMethod = Automatic),
+            &AnalysisContext::from_dir_values([
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentMethod = Card),
+                dirval!(PaymentMethod = Wallet),
+                dirval!(PaymentMethod = PayLater),
+            ]),
+            memo,
+        );
+
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_not_in_aggregator_success() {
+        let graph = knowledge! {crate
+            PaymentMethod(not in [Card, Wallet]) ->> CaptureMethod(Automatic);
+        };
+        let memo = &mut Memoization::new();
+        let result = graph.key_value_analysis(
+            dirval!(CaptureMethod = Automatic),
+            &AnalysisContext::from_dir_values([
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentMethod = PayLater),
+                dirval!(PaymentMethod = BankRedirect),
+            ]),
+            memo,
+        );
+
+        assert!(result.is_ok());
+    }
+
+    #[test]
+    fn test_not_in_aggregator_failure() {
+        let graph = knowledge! {crate
+            PaymentMethod(not in [Card, Wallet]) ->> CaptureMethod(Automatic);
+        };
+        let memo = &mut Memoization::new();
+        let result = graph.key_value_analysis(
+            dirval!(CaptureMethod = Automatic),
+            &AnalysisContext::from_dir_values([
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentMethod = PayLater),
+                dirval!(PaymentMethod = BankRedirect),
+                dirval!(PaymentMethod = Card),
+            ]),
+            memo,
+        );
+
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_in_aggregator_failure_trace() {
+        let graph = knowledge! {crate
+            PaymentMethod(in [Card, Wallet]) ->> CaptureMethod(Automatic);
+        };
+        let memo = &mut Memoization::new();
+        let result = graph.key_value_analysis(
+            dirval!(CaptureMethod = Automatic),
+            &AnalysisContext::from_dir_values([
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentMethod = Card),
+                dirval!(PaymentMethod = Wallet),
+                dirval!(PaymentMethod = PayLater),
+            ]),
+            memo,
+        );
+
+        if let AnalysisTrace::Value {
+            predecessors: Some(ValueTracePredecessor::Mandatory(agg_error)),
+            ..
+        } = Weak::upgrade(&result.unwrap_err().get_analysis_trace().unwrap())
+            .expect("Expected arc")
+            .deref()
+        {
+            assert!(matches!(
+                *Weak::upgrade(agg_error.deref()).expect("Expected Arc"),
+                AnalysisTrace::InAggregation {
+                    found: Some(dir::DirValue::PaymentMethod(enums::PaymentMethod::PayLater)),
+                    ..
+                }
+            ));
+        } else {
+            panic!("Failed unwrapping OnlyInAggregation trace from AnalysisTrace");
+        }
+    }
+
+    #[test]
+    fn _test_memoization_in_kgraph() {
+        let mut builder = KnowledgeGraphBuilder::new();
+        let _node_1 = builder.make_value_node(
+            NodeValue::Value(dir::DirValue::PaymentMethod(enums::PaymentMethod::Wallet)),
+            None,
+            Vec::new(),
+            None::<()>,
+        );
+        let _node_2 = builder.make_value_node(
+            NodeValue::Value(dir::DirValue::BillingCountry(enums::BillingCountry::India)),
+            None,
+            Vec::new(),
+            None::<()>,
+        );
+        let _node_3 = builder.make_value_node(
+            NodeValue::Value(dir::DirValue::BusinessCountry(
+                enums::BusinessCountry::UnitedStatesOfAmerica,
+            )),
+            None,
+            Vec::new(),
+            None::<()>,
+        );
+        let mut memo = Memoization::new();
+        let _edge_1 = builder
+            .make_edge(
+                _node_1.expect("node1 constructtion failed"),
+                _node_2.clone().expect("node2 construction failed"),
+                Strength::Strong,
+                Relation::Positive,
+            )
+            .expect("Failed to make an edge");
+        let _edge_2 = builder
+            .make_edge(
+                _node_2.expect("node2 construction failed"),
+                _node_3.clone().expect("node3 construction failed"),
+                Strength::Strong,
+                Relation::Positive,
+            )
+            .expect("Failed to an edge");
+        let graph = builder.build();
+        let _result = graph.key_value_analysis(
+            dirval!(BusinessCountry = UnitedStatesOfAmerica),
+            &AnalysisContext::from_dir_values([
+                dirval!(PaymentMethod = Wallet),
+                dirval!(BillingCountry = India),
+                dirval!(BusinessCountry = UnitedStatesOfAmerica),
+            ]),
+            &mut memo,
+        );
+        let _ans = memo
+            .0
+            .get(&(
+                _node_3.expect("node3 construction failed"),
+                Relation::Positive,
+                Strength::Strong,
+            ))
+            .expect("Memoization not workng");
+        matches!(_ans, Ok(()));
+    }
+}
diff --git a/crates/euclid/src/dssa/state_machine.rs b/crates/euclid/src/dssa/state_machine.rs
new file mode 100644
index 000000000000..4cd53911dfe4
--- /dev/null
+++ b/crates/euclid/src/dssa/state_machine.rs
@@ -0,0 +1,714 @@
+use super::types::EuclidAnalysable;
+use crate::{dssa::types, frontend::dir, types::Metadata};
+
+#[derive(Debug, Clone, serde::Serialize, thiserror::Error)]
+#[serde(tag = "type", content = "info", rename_all = "snake_case")]
+pub enum StateMachineError {
+    #[error("Index out of bounds: {0}")]
+    IndexOutOfBounds(&'static str),
+}
+
+#[derive(Debug)]
+struct ComparisonStateMachine<'a> {
+    values: &'a [dir::DirValue],
+    logic: &'a dir::DirComparisonLogic,
+    metadata: &'a Metadata,
+    count: usize,
+    ctx_idx: usize,
+}
+
+impl<'a> ComparisonStateMachine<'a> {
+    #[inline]
+    fn is_finished(&self) -> bool {
+        self.count + 1 >= self.values.len()
+            || matches!(self.logic, dir::DirComparisonLogic::NegativeConjunction)
+    }
+
+    #[inline]
+    fn advance(&mut self) {
+        if let dir::DirComparisonLogic::PositiveDisjunction = self.logic {
+            self.count = (self.count + 1) % self.values.len();
+        }
+    }
+
+    #[inline]
+    fn reset(&mut self) {
+        self.count = 0;
+    }
+
+    #[inline]
+    fn put(&self, context: &mut types::ConjunctiveContext<'a>) -> Result<(), StateMachineError> {
+        if let dir::DirComparisonLogic::PositiveDisjunction = self.logic {
+            *context
+                .get_mut(self.ctx_idx)
+                .ok_or(StateMachineError::IndexOutOfBounds(
+                    "in ComparisonStateMachine while indexing into context",
+                ))? = types::ContextValue::assertion(
+                self.values
+                    .get(self.count)
+                    .ok_or(StateMachineError::IndexOutOfBounds(
+                        "in ComparisonStateMachine while indexing into values",
+                    ))?,
+                self.metadata,
+            );
+        }
+        Ok(())
+    }
+
+    #[inline]
+    fn push(&self, context: &mut types::ConjunctiveContext<'a>) -> Result<(), StateMachineError> {
+        match self.logic {
+            dir::DirComparisonLogic::PositiveDisjunction => {
+                context.push(types::ContextValue::assertion(
+                    self.values
+                        .get(self.count)
+                        .ok_or(StateMachineError::IndexOutOfBounds(
+                            "in ComparisonStateMachine while pushing",
+                        ))?,
+                    self.metadata,
+                ));
+            }
+
+            dir::DirComparisonLogic::NegativeConjunction => {
+                context.push(types::ContextValue::negation(self.values, self.metadata));
+            }
+        }
+        Ok(())
+    }
+}
+
+#[derive(Debug)]
+struct ConditionStateMachine<'a> {
+    state_machines: Vec<ComparisonStateMachine<'a>>,
+    start_ctx_idx: usize,
+}
+
+impl<'a> ConditionStateMachine<'a> {
+    fn new(condition: &'a [dir::DirComparison], start_idx: usize) -> Self {
+        let mut machines = Vec::<ComparisonStateMachine<'a>>::with_capacity(condition.len());
+
+        let mut machine_idx = start_idx;
+        for cond in condition {
+            let machine = ComparisonStateMachine {
+                values: &cond.values,
+                logic: &cond.logic,
+                metadata: &cond.metadata,
+                count: 0,
+                ctx_idx: machine_idx,
+            };
+            machines.push(machine);
+            machine_idx += 1;
+        }
+
+        Self {
+            state_machines: machines,
+            start_ctx_idx: start_idx,
+        }
+    }
+
+    fn init(&self, context: &mut types::ConjunctiveContext<'a>) -> Result<(), StateMachineError> {
+        for machine in &self.state_machines {
+            machine.push(context)?;
+        }
+        Ok(())
+    }
+
+    #[inline]
+    fn destroy(&self, context: &mut types::ConjunctiveContext<'a>) {
+        context.truncate(self.start_ctx_idx);
+    }
+
+    #[inline]
+    fn is_finished(&self) -> bool {
+        !self
+            .state_machines
+            .iter()
+            .any(|machine| !machine.is_finished())
+    }
+
+    #[inline]
+    fn get_next_ctx_idx(&self) -> usize {
+        self.start_ctx_idx + self.state_machines.len()
+    }
+
+    fn advance(
+        &mut self,
+        context: &mut types::ConjunctiveContext<'a>,
+    ) -> Result<(), StateMachineError> {
+        for machine in self.state_machines.iter_mut().rev() {
+            if machine.is_finished() {
+                machine.reset();
+                machine.put(context)?;
+            } else {
+                machine.advance();
+                machine.put(context)?;
+                break;
+            }
+        }
+        Ok(())
+    }
+}
+
+#[derive(Debug)]
+struct IfStmtStateMachine<'a> {
+    condition_machine: ConditionStateMachine<'a>,
+    nested: Vec<&'a dir::DirIfStatement>,
+    nested_idx: usize,
+}
+
+impl<'a> IfStmtStateMachine<'a> {
+    fn new(stmt: &'a dir::DirIfStatement, ctx_start_idx: usize) -> Self {
+        let condition_machine = ConditionStateMachine::new(&stmt.condition, ctx_start_idx);
+        let nested: Vec<&'a dir::DirIfStatement> = match &stmt.nested {
+            None => Vec::new(),
+            Some(nested_stmts) => nested_stmts.iter().collect(),
+        };
+
+        Self {
+            condition_machine,
+            nested,
+            nested_idx: 0,
+        }
+    }
+
+    fn init(
+        &self,
+        context: &mut types::ConjunctiveContext<'a>,
+    ) -> Result<Option<Self>, StateMachineError> {
+        self.condition_machine.init(context)?;
+        Ok(self
+            .nested
+            .first()
+            .map(|nested| Self::new(nested, self.condition_machine.get_next_ctx_idx())))
+    }
+
+    #[inline]
+    fn is_finished(&self) -> bool {
+        self.nested_idx + 1 >= self.nested.len()
+    }
+
+    #[inline]
+    fn is_condition_machine_finished(&self) -> bool {
+        self.condition_machine.is_finished()
+    }
+
+    #[inline]
+    fn destroy(&self, context: &mut types::ConjunctiveContext<'a>) {
+        self.condition_machine.destroy(context);
+    }
+
+    #[inline]
+    fn advance_condition_machine(
+        &mut self,
+        context: &mut types::ConjunctiveContext<'a>,
+    ) -> Result<(), StateMachineError> {
+        self.condition_machine.advance(context)?;
+        Ok(())
+    }
+
+    fn advance(&mut self) -> Result<Option<Self>, StateMachineError> {
+        if self.nested.is_empty() {
+            Ok(None)
+        } else {
+            self.nested_idx = (self.nested_idx + 1) % self.nested.len();
+            Ok(Some(Self::new(
+                self.nested
+                    .get(self.nested_idx)
+                    .ok_or(StateMachineError::IndexOutOfBounds(
+                        "in IfStmtStateMachine while advancing",
+                    ))?,
+                self.condition_machine.get_next_ctx_idx(),
+            )))
+        }
+    }
+}
+
+#[derive(Debug)]
+struct RuleStateMachine<'a> {
+    connector_selection_data: &'a [(dir::DirValue, Metadata)],
+    connectors_added: bool,
+    if_stmt_machines: Vec<IfStmtStateMachine<'a>>,
+    running_stack: Vec<IfStmtStateMachine<'a>>,
+}
+
+impl<'a> RuleStateMachine<'a> {
+    fn new<O>(
+        rule: &'a dir::DirRule<O>,
+        connector_selection_data: &'a [(dir::DirValue, Metadata)],
+    ) -> Self {
+        let mut if_stmt_machines: Vec<IfStmtStateMachine<'a>> =
+            Vec::with_capacity(rule.statements.len());
+
+        for stmt in rule.statements.iter().rev() {
+            if_stmt_machines.push(IfStmtStateMachine::new(
+                stmt,
+                connector_selection_data.len(),
+            ));
+        }
+
+        Self {
+            connector_selection_data,
+            connectors_added: false,
+            if_stmt_machines,
+            running_stack: Vec::new(),
+        }
+    }
+
+    fn is_finished(&self) -> bool {
+        self.if_stmt_machines.is_empty() && self.running_stack.is_empty()
+    }
+
+    fn init_next(
+        &mut self,
+        context: &mut types::ConjunctiveContext<'a>,
+    ) -> Result<(), StateMachineError> {
+        if self.if_stmt_machines.is_empty() || !self.running_stack.is_empty() {
+            return Ok(());
+        }
+
+        if !self.connectors_added {
+            for (dir_val, metadata) in self.connector_selection_data {
+                context.push(types::ContextValue::assertion(dir_val, metadata));
+            }
+            self.connectors_added = true;
+        }
+
+        context.truncate(self.connector_selection_data.len());
+
+        if let Some(mut next_running) = self.if_stmt_machines.pop() {
+            while let Some(nested_running) = next_running.init(context)? {
+                self.running_stack.push(next_running);
+                next_running = nested_running;
+            }
+
+            self.running_stack.push(next_running);
+        }
+
+        Ok(())
+    }
+
+    fn advance(
+        &mut self,
+        context: &mut types::ConjunctiveContext<'a>,
+    ) -> Result<(), StateMachineError> {
+        let mut condition_machines_finished = true;
+
+        for stmt_machine in self.running_stack.iter_mut().rev() {
+            if !stmt_machine.is_condition_machine_finished() {
+                condition_machines_finished = false;
+                stmt_machine.advance_condition_machine(context)?;
+                break;
+            } else {
+                stmt_machine.advance_condition_machine(context)?;
+            }
+        }
+
+        if !condition_machines_finished {
+            return Ok(());
+        }
+
+        let mut maybe_next_running: Option<IfStmtStateMachine<'a>> = None;
+
+        while let Some(last) = self.running_stack.last_mut() {
+            if !last.is_finished() {
+                maybe_next_running = last.advance()?;
+                break;
+            } else {
+                last.destroy(context);
+                self.running_stack.pop();
+            }
+        }
+
+        if let Some(mut next_running) = maybe_next_running {
+            while let Some(nested_running) = next_running.init(context)? {
+                self.running_stack.push(next_running);
+                next_running = nested_running;
+            }
+
+            self.running_stack.push(next_running);
+        } else {
+            self.init_next(context)?;
+        }
+
+        Ok(())
+    }
+}
+
+#[derive(Debug)]
+pub struct RuleContextManager<'a> {
+    context: types::ConjunctiveContext<'a>,
+    machine: RuleStateMachine<'a>,
+    init: bool,
+}
+
+impl<'a> RuleContextManager<'a> {
+    pub fn new<O>(
+        rule: &'a dir::DirRule<O>,
+        connector_selection_data: &'a [(dir::DirValue, Metadata)],
+    ) -> Self {
+        Self {
+            context: Vec::new(),
+            machine: RuleStateMachine::new(rule, connector_selection_data),
+            init: false,
+        }
+    }
+
+    pub fn advance(&mut self) -> Result<Option<&types::ConjunctiveContext<'a>>, StateMachineError> {
+        if !self.init {
+            self.init = true;
+            self.machine.init_next(&mut self.context)?;
+            Ok(Some(&self.context))
+        } else if self.machine.is_finished() {
+            Ok(None)
+        } else {
+            self.machine.advance(&mut self.context)?;
+
+            if self.machine.is_finished() {
+                Ok(None)
+            } else {
+                Ok(Some(&self.context))
+            }
+        }
+    }
+
+    pub fn advance_mut(
+        &mut self,
+    ) -> Result<Option<&mut types::ConjunctiveContext<'a>>, StateMachineError> {
+        if !self.init {
+            self.init = true;
+            self.machine.init_next(&mut self.context)?;
+            Ok(Some(&mut self.context))
+        } else if self.machine.is_finished() {
+            Ok(None)
+        } else {
+            self.machine.advance(&mut self.context)?;
+
+            if self.machine.is_finished() {
+                Ok(None)
+            } else {
+                Ok(Some(&mut self.context))
+            }
+        }
+    }
+}
+
+#[derive(Debug)]
+pub struct ProgramStateMachine<'a> {
+    rule_machines: Vec<RuleStateMachine<'a>>,
+    current_rule_machine: Option<RuleStateMachine<'a>>,
+    is_init: bool,
+}
+
+impl<'a> ProgramStateMachine<'a> {
+    pub fn new<O>(
+        program: &'a dir::DirProgram<O>,
+        connector_selection_data: &'a [Vec<(dir::DirValue, Metadata)>],
+    ) -> Self {
+        let mut rule_machines: Vec<RuleStateMachine<'a>> = program
+            .rules
+            .iter()
+            .zip(connector_selection_data.iter())
+            .rev()
+            .map(|(rule, connector_selection_data)| {
+                RuleStateMachine::new(rule, connector_selection_data)
+            })
+            .collect();
+
+        Self {
+            current_rule_machine: rule_machines.pop(),
+            rule_machines,
+            is_init: false,
+        }
+    }
+
+    pub fn is_finished(&self) -> bool {
+        self.current_rule_machine
+            .as_ref()
+            .map_or(true, |rsm| rsm.is_finished())
+            && self.rule_machines.is_empty()
+    }
+
+    pub fn init(
+        &mut self,
+        context: &mut types::ConjunctiveContext<'a>,
+    ) -> Result<(), StateMachineError> {
+        if !self.is_init {
+            if let Some(rsm) = self.current_rule_machine.as_mut() {
+                rsm.init_next(context)?;
+            }
+            self.is_init = true;
+        }
+
+        Ok(())
+    }
+
+    pub fn advance(
+        &mut self,
+        context: &mut types::ConjunctiveContext<'a>,
+    ) -> Result<(), StateMachineError> {
+        if self
+            .current_rule_machine
+            .as_ref()
+            .map_or(true, |rsm| rsm.is_finished())
+        {
+            self.current_rule_machine = self.rule_machines.pop();
+            context.clear();
+            if let Some(rsm) = self.current_rule_machine.as_mut() {
+                rsm.init_next(context)?;
+            }
+        } else if let Some(rsm) = self.current_rule_machine.as_mut() {
+            rsm.advance(context)?;
+        }
+
+        Ok(())
+    }
+}
+
+pub struct AnalysisContextManager<'a> {
+    context: types::ConjunctiveContext<'a>,
+    machine: ProgramStateMachine<'a>,
+    init: bool,
+}
+
+impl<'a> AnalysisContextManager<'a> {
+    pub fn new<O>(
+        program: &'a dir::DirProgram<O>,
+        connector_selection_data: &'a [Vec<(dir::DirValue, Metadata)>],
+    ) -> Self {
+        let machine = ProgramStateMachine::new(program, connector_selection_data);
+        let context: types::ConjunctiveContext<'a> = Vec::new();
+
+        Self {
+            context,
+            machine,
+            init: false,
+        }
+    }
+
+    pub fn advance(&mut self) -> Result<Option<&types::ConjunctiveContext<'a>>, StateMachineError> {
+        if !self.init {
+            self.init = true;
+            self.machine.init(&mut self.context)?;
+            Ok(Some(&self.context))
+        } else if self.machine.is_finished() {
+            Ok(None)
+        } else {
+            self.machine.advance(&mut self.context)?;
+
+            if self.machine.is_finished() {
+                Ok(None)
+            } else {
+                Ok(Some(&self.context))
+            }
+        }
+    }
+}
+
+pub fn make_connector_selection_data<O: EuclidAnalysable>(
+    program: &dir::DirProgram<O>,
+) -> Vec<Vec<(dir::DirValue, Metadata)>> {
+    program
+        .rules
+        .iter()
+        .map(|rule| {
+            rule.connector_selection
+                .get_dir_value_for_analysis(rule.name.clone())
+        })
+        .collect()
+}
+
+#[cfg(all(test, feature = "ast_parser"))]
+mod tests {
+    #![allow(clippy::expect_used)]
+
+    use super::*;
+    use crate::{dirval, frontend::ast, types::DummyOutput};
+
+    #[test]
+    fn test_correct_contexts() {
+        let program_str = r#"
+            default: ["stripe", "adyen"]
+
+            stripe_first: ["stripe", "adyen"]
+            {
+                payment_method = wallet {
+                    payment_method = (card, bank_redirect) {
+                        currency = USD
+                        currency = GBP
+                    }
+
+                    payment_method = pay_later {
+                        capture_method = automatic
+                        capture_method = manual
+                    }
+                }
+
+                payment_method = card {
+                    payment_method = (card, bank_redirect) & capture_method = (automatic, manual) {
+                        currency = (USD, GBP)
+                    }
+                }
+            }
+        "#;
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+        let lowered = ast::lowering::lower_program(program).expect("Lowering");
+
+        let selection_data = make_connector_selection_data(&lowered);
+        let mut state_machine = ProgramStateMachine::new(&lowered, &selection_data);
+        let mut ctx: types::ConjunctiveContext<'_> = Vec::new();
+        state_machine.init(&mut ctx).expect("State machine init");
+
+        let expected_contexts: Vec<Vec<dir::DirValue>> = vec![
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Wallet),
+                dirval!(PaymentMethod = Card),
+                dirval!(PaymentCurrency = USD),
+            ],
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Wallet),
+                dirval!(PaymentMethod = BankRedirect),
+                dirval!(PaymentCurrency = USD),
+            ],
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Wallet),
+                dirval!(PaymentMethod = Card),
+                dirval!(PaymentCurrency = GBP),
+            ],
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Wallet),
+                dirval!(PaymentMethod = BankRedirect),
+                dirval!(PaymentCurrency = GBP),
+            ],
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Wallet),
+                dirval!(PaymentMethod = PayLater),
+                dirval!(CaptureMethod = Automatic),
+            ],
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Wallet),
+                dirval!(PaymentMethod = PayLater),
+                dirval!(CaptureMethod = Manual),
+            ],
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Card),
+                dirval!(PaymentMethod = Card),
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentCurrency = USD),
+            ],
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Card),
+                dirval!(PaymentMethod = Card),
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentCurrency = GBP),
+            ],
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Card),
+                dirval!(PaymentMethod = Card),
+                dirval!(CaptureMethod = Manual),
+                dirval!(PaymentCurrency = USD),
+            ],
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Card),
+                dirval!(PaymentMethod = Card),
+                dirval!(CaptureMethod = Manual),
+                dirval!(PaymentCurrency = GBP),
+            ],
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Card),
+                dirval!(PaymentMethod = BankRedirect),
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentCurrency = USD),
+            ],
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Card),
+                dirval!(PaymentMethod = BankRedirect),
+                dirval!(CaptureMethod = Automatic),
+                dirval!(PaymentCurrency = GBP),
+            ],
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Card),
+                dirval!(PaymentMethod = BankRedirect),
+                dirval!(CaptureMethod = Manual),
+                dirval!(PaymentCurrency = USD),
+            ],
+            vec![
+                dirval!("MetadataKey" = "stripe"),
+                dirval!("MetadataKey" = "adyen"),
+                dirval!(PaymentMethod = Card),
+                dirval!(PaymentMethod = BankRedirect),
+                dirval!(CaptureMethod = Manual),
+                dirval!(PaymentCurrency = GBP),
+            ],
+        ];
+
+        let mut expected_idx = 0usize;
+        while !state_machine.is_finished() {
+            let values = ctx
+                .iter()
+                .flat_map(|c| match c.value {
+                    types::CtxValueKind::Assertion(val) => vec![val],
+                    types::CtxValueKind::Negation(vals) => vals.iter().collect(),
+                })
+                .collect::<Vec<&dir::DirValue>>();
+            assert_eq!(
+                values,
+                expected_contexts[expected_idx]
+                    .iter()
+                    .collect::<Vec<&dir::DirValue>>()
+            );
+            expected_idx += 1;
+            state_machine
+                .advance(&mut ctx)
+                .expect("State Machine advance");
+        }
+
+        assert_eq!(expected_idx, 14);
+
+        let mut ctx_manager = AnalysisContextManager::new(&lowered, &selection_data);
+        expected_idx = 0;
+        while let Some(ctx) = ctx_manager.advance().expect("Context Manager Context") {
+            let values = ctx
+                .iter()
+                .flat_map(|c| match c.value {
+                    types::CtxValueKind::Assertion(val) => vec![val],
+                    types::CtxValueKind::Negation(vals) => vals.iter().collect(),
+                })
+                .collect::<Vec<&dir::DirValue>>();
+            assert_eq!(
+                values,
+                expected_contexts[expected_idx]
+                    .iter()
+                    .collect::<Vec<&dir::DirValue>>()
+            );
+            expected_idx += 1;
+        }
+
+        assert_eq!(expected_idx, 14);
+    }
+}
diff --git a/crates/euclid/src/dssa/truth.rs b/crates/euclid/src/dssa/truth.rs
new file mode 100644
index 000000000000..17e6e728e68f
--- /dev/null
+++ b/crates/euclid/src/dssa/truth.rs
@@ -0,0 +1,29 @@
+use euclid_macros::knowledge;
+use once_cell::sync::Lazy;
+
+use crate::dssa::graph;
+
+pub static ANALYSIS_GRAPH: Lazy<graph::KnowledgeGraph<'_>> = Lazy::new(|| {
+    knowledge! {crate
+        // Payment Method should be `Card` for a CardType to be present
+        PaymentMethod(Card) ->> CardType(any);
+
+        // Payment Method should be `PayLater` for a PayLaterType to be present
+        PaymentMethod(PayLater) ->> PayLaterType(any);
+
+        // Payment Method should be `Wallet` for a WalletType to be present
+        PaymentMethod(Wallet) ->> WalletType(any);
+
+        // Payment Method should be `BankRedirect` for a BankRedirectType to
+        // be present
+        PaymentMethod(BankRedirect) ->> BankRedirectType(any);
+
+        // Payment Method should be `BankTransfer` for a BankTransferType to
+        // be present
+        PaymentMethod(BankTransfer) ->> BankTransferType(any);
+
+        // Payment Method should be `GiftCard` for a GiftCardType to
+        // be present
+        PaymentMethod(GiftCard) ->> GiftCardType(any);
+    }
+});
diff --git a/crates/euclid/src/dssa/types.rs b/crates/euclid/src/dssa/types.rs
new file mode 100644
index 000000000000..4070e0825ef7
--- /dev/null
+++ b/crates/euclid/src/dssa/types.rs
@@ -0,0 +1,158 @@
+use std::fmt;
+
+use serde::Serialize;
+
+use crate::{
+    dssa::{self, graph},
+    frontend::{ast, dir},
+    types::{DataType, EuclidValue, Metadata},
+};
+
+pub trait EuclidAnalysable: Sized {
+    fn get_dir_value_for_analysis(&self, rule_name: String) -> Vec<(dir::DirValue, Metadata)>;
+}
+
+#[derive(Debug, Clone)]
+pub enum CtxValueKind<'a> {
+    Assertion(&'a dir::DirValue),
+    Negation(&'a [dir::DirValue]),
+}
+
+impl<'a> CtxValueKind<'a> {
+    pub fn get_assertion(&self) -> Option<&dir::DirValue> {
+        if let Self::Assertion(val) = self {
+            Some(val)
+        } else {
+            None
+        }
+    }
+
+    pub fn get_negation(&self) -> Option<&[dir::DirValue]> {
+        if let Self::Negation(vals) = self {
+            Some(vals)
+        } else {
+            None
+        }
+    }
+
+    pub fn get_key(&self) -> Option<dir::DirKey> {
+        match self {
+            Self::Assertion(val) => Some(val.get_key()),
+            Self::Negation(vals) => vals.first().map(|v| (*v).get_key()),
+        }
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct ContextValue<'a> {
+    pub value: CtxValueKind<'a>,
+    pub metadata: &'a Metadata,
+}
+
+impl<'a> ContextValue<'a> {
+    #[inline]
+    pub fn assertion(value: &'a dir::DirValue, metadata: &'a Metadata) -> Self {
+        Self {
+            value: CtxValueKind::Assertion(value),
+            metadata,
+        }
+    }
+
+    #[inline]
+    pub fn negation(values: &'a [dir::DirValue], metadata: &'a Metadata) -> Self {
+        Self {
+            value: CtxValueKind::Negation(values),
+            metadata,
+        }
+    }
+}
+
+pub type ConjunctiveContext<'a> = Vec<ContextValue<'a>>;
+
+#[derive(Clone, Serialize)]
+pub enum AnalyzeResult {
+    AllOk,
+}
+
+#[derive(Debug, Clone, Serialize, thiserror::Error)]
+pub struct AnalysisError {
+    #[serde(flatten)]
+    pub error_type: AnalysisErrorType,
+    pub metadata: Metadata,
+}
+impl fmt::Display for AnalysisError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.error_type.fmt(f)
+    }
+}
+#[derive(Debug, Clone, Serialize)]
+pub struct ValueData {
+    pub value: dir::DirValue,
+    pub metadata: Metadata,
+}
+
+#[derive(Debug, Clone, Serialize, thiserror::Error)]
+#[serde(tag = "type", content = "info", rename_all = "snake_case")]
+pub enum AnalysisErrorType {
+    #[error("Invalid program key given: '{0}'")]
+    InvalidKey(String),
+    #[error("Invalid variant '{got}' received for key '{key}'")]
+    InvalidVariant {
+        key: String,
+        expected: Vec<String>,
+        got: String,
+    },
+    #[error(
+        "Invalid data type for value '{}' (expected {expected}, got {got})",
+        key
+    )]
+    InvalidType {
+        key: String,
+        expected: DataType,
+        got: DataType,
+    },
+    #[error("Invalid comparison '{operator:?}' for value type {value_type}")]
+    InvalidComparison {
+        operator: ast::ComparisonType,
+        value_type: DataType,
+    },
+    #[error("Invalid value received for length as '{value}: {:?}'", message)]
+    InvalidValue {
+        key: dir::DirKeyKind,
+        value: String,
+        message: Option<String>,
+    },
+    #[error("Conflicting assertions received for key '{}'", .key.kind)]
+    ConflictingAssertions {
+        key: dir::DirKey,
+        values: Vec<ValueData>,
+    },
+
+    #[error("Key '{}' exhaustively negated", .key.kind)]
+    ExhaustiveNegation {
+        key: dir::DirKey,
+        metadata: Vec<Metadata>,
+    },
+    #[error("The condition '{value}' was asserted and negated in the same condition")]
+    NegatedAssertion {
+        value: dir::DirValue,
+        assertion_metadata: Metadata,
+        negation_metadata: Metadata,
+    },
+    #[error("Graph analysis error: {0:#?}")]
+    GraphAnalysis(graph::AnalysisError, graph::Memoization),
+    #[error("State machine error")]
+    StateMachine(dssa::state_machine::StateMachineError),
+    #[error("Unsupported program key '{0}'")]
+    UnsupportedProgramKey(dir::DirKeyKind),
+    #[error("Ran into an unimplemented feature")]
+    NotImplemented,
+    #[error("The payment method type is not supported under the payment method")]
+    NotSupported,
+}
+
+#[derive(Debug, Clone)]
+pub enum ValueType {
+    EnumVariants(Vec<EuclidValue>),
+    Number,
+}
diff --git a/crates/euclid/src/dssa/utils.rs b/crates/euclid/src/dssa/utils.rs
new file mode 100644
index 000000000000..df4ff82cbdb7
--- /dev/null
+++ b/crates/euclid/src/dssa/utils.rs
@@ -0,0 +1 @@
+pub struct Unpacker;
diff --git a/crates/euclid/src/enums.rs b/crates/euclid/src/enums.rs
new file mode 100644
index 000000000000..4188860ab90f
--- /dev/null
+++ b/crates/euclid/src/enums.rs
@@ -0,0 +1,191 @@
+pub use common_enums::{
+    AuthenticationType, CaptureMethod, CardNetwork, Country, Currency,
+    FutureUsage as SetupFutureUsage, PaymentMethod, PaymentMethodType,
+};
+use serde::{Deserialize, Serialize};
+use strum::VariantNames;
+
+pub trait CollectVariants {
+    fn variants<T: FromIterator<String>>() -> T;
+}
+macro_rules! collect_variants {
+    ($the_enum:ident) => {
+        impl $crate::enums::CollectVariants for $the_enum {
+            fn variants<T>() -> T
+            where
+                T: FromIterator<String>,
+            {
+                Self::VARIANTS.iter().map(|s| String::from(*s)).collect()
+            }
+        }
+    };
+}
+
+pub(crate) use collect_variants;
+
+collect_variants!(PaymentMethod);
+collect_variants!(PaymentType);
+collect_variants!(MandateType);
+collect_variants!(MandateAcceptanceType);
+collect_variants!(PaymentMethodType);
+collect_variants!(CardNetwork);
+collect_variants!(AuthenticationType);
+collect_variants!(CaptureMethod);
+collect_variants!(Currency);
+collect_variants!(Country);
+collect_variants!(Connector);
+collect_variants!(SetupFutureUsage);
+
+#[derive(
+    Debug,
+    Copy,
+    Clone,
+    PartialEq,
+    Eq,
+    Hash,
+    Serialize,
+    Deserialize,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    frunk::LabelledGeneric,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum Connector {
+    #[cfg(feature = "dummy_connector")]
+    #[serde(rename = "phonypay")]
+    #[strum(serialize = "phonypay")]
+    DummyConnector1,
+    #[cfg(feature = "dummy_connector")]
+    #[serde(rename = "fauxpay")]
+    #[strum(serialize = "fauxpay")]
+    DummyConnector2,
+    #[cfg(feature = "dummy_connector")]
+    #[serde(rename = "pretendpay")]
+    #[strum(serialize = "pretendpay")]
+    DummyConnector3,
+    #[cfg(feature = "dummy_connector")]
+    #[serde(rename = "stripe_test")]
+    #[strum(serialize = "stripe_test")]
+    DummyConnector4,
+    #[cfg(feature = "dummy_connector")]
+    #[serde(rename = "adyen_test")]
+    #[strum(serialize = "adyen_test")]
+    DummyConnector5,
+    #[cfg(feature = "dummy_connector")]
+    #[serde(rename = "checkout_test")]
+    #[strum(serialize = "checkout_test")]
+    DummyConnector6,
+    #[cfg(feature = "dummy_connector")]
+    #[serde(rename = "paypal_test")]
+    #[strum(serialize = "paypal_test")]
+    DummyConnector7,
+    Aci,
+    Adyen,
+    Airwallex,
+    Authorizedotnet,
+    Bitpay,
+    Bambora,
+    Bluesnap,
+    Boku,
+    Braintree,
+    Cashtocode,
+    Checkout,
+    Coinbase,
+    Cryptopay,
+    Cybersource,
+    Dlocal,
+    Fiserv,
+    Forte,
+    Globalpay,
+    Globepay,
+    Gocardless,
+    Helcim,
+    Iatapay,
+    Klarna,
+    Mollie,
+    Multisafepay,
+    Nexinets,
+    Nmi,
+    Noon,
+    Nuvei,
+    Opennode,
+    Payme,
+    Paypal,
+    Payu,
+    Powertranz,
+    Rapyd,
+    Shift4,
+    Square,
+    Stax,
+    Stripe,
+    Trustpay,
+    Tsys,
+    Volt,
+    Wise,
+    Worldline,
+    Worldpay,
+    Zen,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum MandateAcceptanceType {
+    Online,
+    Offline,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum PaymentType {
+    SetupMandate,
+    NonMandate,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum MandateType {
+    SingleUse,
+    MultiUse,
+}
diff --git a/crates/euclid/src/frontend.rs b/crates/euclid/src/frontend.rs
new file mode 100644
index 000000000000..17fc8f3502e2
--- /dev/null
+++ b/crates/euclid/src/frontend.rs
@@ -0,0 +1,3 @@
+pub mod ast;
+pub mod dir;
+pub mod vir;
diff --git a/crates/euclid/src/frontend/ast.rs b/crates/euclid/src/frontend/ast.rs
new file mode 100644
index 000000000000..3adb06ab1873
--- /dev/null
+++ b/crates/euclid/src/frontend/ast.rs
@@ -0,0 +1,156 @@
+pub mod lowering;
+#[cfg(feature = "ast_parser")]
+pub mod parser;
+
+use serde::{Deserialize, Serialize};
+
+use crate::{
+    enums::Connector,
+    types::{DataType, Metadata},
+};
+
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+pub struct ConnectorChoice {
+    pub connector: Connector,
+    #[cfg(not(feature = "connector_choice_mca_id"))]
+    pub sub_label: Option<String>,
+}
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub struct MetadataValue {
+    pub key: String,
+    pub value: String,
+}
+
+/// Represents a value in the DSL
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(tag = "type", content = "value", rename_all = "snake_case")]
+pub enum ValueType {
+    /// Represents a number literal
+    Number(i64),
+    /// Represents an enum variant
+    EnumVariant(String),
+    /// Represents a Metadata variant
+    MetadataVariant(MetadataValue),
+    /// Represents a arbitrary String value
+    StrValue(String),
+    /// Represents an array of numbers. This is basically used for
+    /// "one of the given numbers" operations
+    /// eg: payment.method.amount = (1, 2, 3)
+    NumberArray(Vec<i64>),
+    /// Similar to NumberArray but for enum variants
+    /// eg: payment.method.cardtype = (debit, credit)
+    EnumVariantArray(Vec<String>),
+    /// Like a number array but can include comparisons. Useful for
+    /// conditions like "500 < amount < 1000"
+    /// eg: payment.amount = (> 500, < 1000)
+    NumberComparisonArray(Vec<NumberComparison>),
+}
+
+impl ValueType {
+    pub fn get_type(&self) -> DataType {
+        match self {
+            Self::Number(_) => DataType::Number,
+            Self::StrValue(_) => DataType::StrValue,
+            Self::MetadataVariant(_) => DataType::MetadataValue,
+            Self::EnumVariant(_) => DataType::EnumVariant,
+            Self::NumberComparisonArray(_) => DataType::Number,
+            Self::NumberArray(_) => DataType::Number,
+            Self::EnumVariantArray(_) => DataType::EnumVariant,
+        }
+    }
+}
+
+/// Represents a number comparison for "NumberComparisonArrayValue"
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct NumberComparison {
+    pub comparison_type: ComparisonType,
+    pub number: i64,
+}
+
+/// Conditional comparison type
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum ComparisonType {
+    Equal,
+    NotEqual,
+    LessThan,
+    LessThanEqual,
+    GreaterThan,
+    GreaterThanEqual,
+}
+
+/// Represents a single comparison condition.
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Comparison {
+    /// The left hand side which will always be a domain input identifier like "payment.method.cardtype"
+    pub lhs: String,
+    /// The comparison operator
+    pub comparison: ComparisonType,
+    /// The value to compare against
+    pub value: ValueType,
+    /// Additional metadata that the Static Analyzer and Backend does not touch.
+    /// This can be used to store useful information for the frontend and is required for communication
+    /// between the static analyzer and the frontend.
+    pub metadata: Metadata,
+}
+
+/// Represents all the conditions of an IF statement
+/// eg:
+///
+/// ```text
+/// payment.method = card & payment.method.cardtype = debit & payment.method.network = diners
+/// ```
+pub type IfCondition = Vec<Comparison>;
+
+/// Represents an IF statement with conditions and optional nested IF statements
+///
+/// ```text
+/// payment.method = card {
+///     payment.method.cardtype = (credit, debit) {
+///         payment.method.network = (amex, rupay, diners)
+///     }
+/// }
+/// ```
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct IfStatement {
+    pub condition: IfCondition,
+    pub nested: Option<Vec<IfStatement>>,
+}
+
+/// Represents a rule
+///
+/// ```text
+/// rule_name: [stripe, adyen, checkout]
+/// {
+///     payment.method = card {
+///         payment.method.cardtype = (credit, debit) {
+///             payment.method.network = (amex, rupay, diners)
+///         }
+///
+///         payment.method.cardtype = credit
+///     }
+/// }
+/// ```
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Rule<O> {
+    pub name: String,
+    #[serde(alias = "routingOutput")]
+    pub connector_selection: O,
+    pub statements: Vec<IfStatement>,
+}
+
+/// The program, having a default connector selection and
+/// a bunch of rules. Also can hold arbitrary metadata.
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Program<O> {
+    pub default_selection: O,
+    pub rules: Vec<Rule<O>>,
+    pub metadata: Metadata,
+}
diff --git a/crates/euclid/src/frontend/ast/lowering.rs b/crates/euclid/src/frontend/ast/lowering.rs
new file mode 100644
index 000000000000..ffce88a35db6
--- /dev/null
+++ b/crates/euclid/src/frontend/ast/lowering.rs
@@ -0,0 +1,377 @@
+//! Analysis for the Lowering logic in ast
+//!
+//!Certain functions that can be used to perform the complete lowering of ast to dir.
+//!This includes lowering of enums, numbers, strings as well as Comparison logics.
+
+use std::str::FromStr;
+
+use crate::{
+    dssa::types::{AnalysisError, AnalysisErrorType},
+    enums::CollectVariants,
+    frontend::{
+        ast,
+        dir::{self, enums as dir_enums, EuclidDirFilter},
+    },
+    types::{self, DataType},
+};
+
+/// lowers the provided key (enum variant) & value to the respective DirValue
+///
+/// For example
+/// ```notrust
+/// CardType = Visa
+/// ```notrust
+///
+/// This serves for the purpose were we have the DirKey as an explicit Enum type and value as one
+/// of the member of the same Enum.
+/// So particularly it lowers a predefined Enum from DirKey to an Enum of DirValue.
+
+macro_rules! lower_enum {
+    ($key:ident, $value:ident) => {
+        match $value {
+            ast::ValueType::EnumVariant(ev) => Ok(vec![dir::DirValue::$key(
+                dir_enums::$key::from_str(&ev).map_err(|_| AnalysisErrorType::InvalidVariant {
+                    key: dir::DirKeyKind::$key.to_string(),
+                    got: ev,
+                    expected: dir_enums::$key::variants(),
+                })?,
+            )]),
+
+            ast::ValueType::EnumVariantArray(eva) => eva
+                .into_iter()
+                .map(|ev| {
+                    Ok(dir::DirValue::$key(
+                        dir_enums::$key::from_str(&ev).map_err(|_| {
+                            AnalysisErrorType::InvalidVariant {
+                                key: dir::DirKeyKind::$key.to_string(),
+                                got: ev,
+                                expected: dir_enums::$key::variants(),
+                            }
+                        })?,
+                    ))
+                })
+                .collect(),
+
+            _ => Err(AnalysisErrorType::InvalidType {
+                key: dir::DirKeyKind::$key.to_string(),
+                expected: DataType::EnumVariant,
+                got: $value.get_type(),
+            }),
+        }
+    };
+}
+
+/// lowers the provided key for a numerical value
+///
+/// For example
+/// ```notrust
+/// payment_amount = 17052001
+/// ```notrust
+/// This is for the cases in which there are numerical values involved and they are lowered
+/// accordingly on basis of the supplied key, currently payment_amount is the only key having this
+/// use case
+
+macro_rules! lower_number {
+    ($key:ident, $value:ident, $comp:ident) => {
+        match $value {
+            ast::ValueType::Number(num) => Ok(vec![dir::DirValue::$key(types::NumValue {
+                number: num,
+                refinement: $comp.into(),
+            })]),
+
+            ast::ValueType::NumberArray(na) => na
+                .into_iter()
+                .map(|num| {
+                    Ok(dir::DirValue::$key(types::NumValue {
+                        number: num,
+                        refinement: $comp.clone().into(),
+                    }))
+                })
+                .collect(),
+
+            ast::ValueType::NumberComparisonArray(nca) => nca
+                .into_iter()
+                .map(|nc| {
+                    Ok(dir::DirValue::$key(types::NumValue {
+                        number: nc.number,
+                        refinement: nc.comparison_type.into(),
+                    }))
+                })
+                .collect(),
+
+            _ => Err(AnalysisErrorType::InvalidType {
+                key: dir::DirKeyKind::$key.to_string(),
+                expected: DataType::Number,
+                got: $value.get_type(),
+            }),
+        }
+    };
+}
+
+/// lowers the provided key & value to the respective DirValue
+///
+/// For example
+/// ```notrust
+/// card_bin = "123456"
+/// ```notrust
+///
+/// This serves for the purpose were we have the DirKey as Card_bin and value as an arbitrary string
+/// So particularly it lowers an arbitrary value to a predefined key.
+
+macro_rules! lower_str {
+    ($key:ident, $value:ident $(, $validation_closure:expr)?) => {
+        match $value {
+            ast::ValueType::StrValue(st) => {
+                $($validation_closure(&st)?;)?
+                Ok(vec![dir::DirValue::$key(types::StrValue { value: st })])
+            }
+            _ => Err(AnalysisErrorType::InvalidType {
+                key: dir::DirKeyKind::$key.to_string(),
+                expected: DataType::StrValue,
+                got: $value.get_type(),
+            }),
+        }
+    };
+}
+
+macro_rules! lower_metadata {
+    ($key:ident, $value:ident) => {
+        match $value {
+            ast::ValueType::MetadataVariant(md) => {
+                Ok(vec![dir::DirValue::$key(types::MetadataValue {
+                    key: md.key,
+                    value: md.value,
+                })])
+            }
+            _ => Err(AnalysisErrorType::InvalidType {
+                key: dir::DirKeyKind::$key.to_string(),
+                expected: DataType::MetadataValue,
+                got: $value.get_type(),
+            }),
+        }
+    };
+}
+/// lowers the comparison operators for different subtle value types present
+/// by throwing required errors for comparisons that can't be performed for a certain value type
+/// for example
+/// can't have greater/less than operations on enum types
+
+fn lower_comparison_inner<O: EuclidDirFilter>(
+    comp: ast::Comparison,
+) -> Result<Vec<dir::DirValue>, AnalysisErrorType> {
+    let key_enum = dir::DirKeyKind::from_str(comp.lhs.as_str())
+        .map_err(|_| AnalysisErrorType::InvalidKey(comp.lhs.clone()))?;
+
+    if !O::is_key_allowed(&key_enum) {
+        return Err(AnalysisErrorType::InvalidKey(key_enum.to_string()));
+    }
+
+    match (&comp.comparison, &comp.value) {
+        (
+            ast::ComparisonType::LessThan
+            | ast::ComparisonType::GreaterThan
+            | ast::ComparisonType::GreaterThanEqual
+            | ast::ComparisonType::LessThanEqual,
+            ast::ValueType::EnumVariant(_),
+        ) => {
+            Err(AnalysisErrorType::InvalidComparison {
+                operator: comp.comparison.clone(),
+                value_type: DataType::EnumVariant,
+            })?;
+        }
+
+        (
+            ast::ComparisonType::LessThan
+            | ast::ComparisonType::GreaterThan
+            | ast::ComparisonType::GreaterThanEqual
+            | ast::ComparisonType::LessThanEqual,
+            ast::ValueType::NumberArray(_),
+        ) => {
+            Err(AnalysisErrorType::InvalidComparison {
+                operator: comp.comparison.clone(),
+                value_type: DataType::Number,
+            })?;
+        }
+
+        (
+            ast::ComparisonType::LessThan
+            | ast::ComparisonType::GreaterThan
+            | ast::ComparisonType::GreaterThanEqual
+            | ast::ComparisonType::LessThanEqual,
+            ast::ValueType::EnumVariantArray(_),
+        ) => {
+            Err(AnalysisErrorType::InvalidComparison {
+                operator: comp.comparison.clone(),
+                value_type: DataType::EnumVariant,
+            })?;
+        }
+
+        (
+            ast::ComparisonType::LessThan
+            | ast::ComparisonType::GreaterThan
+            | ast::ComparisonType::GreaterThanEqual
+            | ast::ComparisonType::LessThanEqual,
+            ast::ValueType::NumberComparisonArray(_),
+        ) => {
+            Err(AnalysisErrorType::InvalidComparison {
+                operator: comp.comparison.clone(),
+                value_type: DataType::Number,
+            })?;
+        }
+
+        _ => {}
+    }
+
+    let value = comp.value;
+    let comparison = comp.comparison;
+
+    match key_enum {
+        dir::DirKeyKind::PaymentMethod => lower_enum!(PaymentMethod, value),
+
+        dir::DirKeyKind::CardType => lower_enum!(CardType, value),
+
+        dir::DirKeyKind::CardNetwork => lower_enum!(CardNetwork, value),
+
+        dir::DirKeyKind::PayLaterType => lower_enum!(PayLaterType, value),
+
+        dir::DirKeyKind::WalletType => lower_enum!(WalletType, value),
+
+        dir::DirKeyKind::BankDebitType => lower_enum!(BankDebitType, value),
+
+        dir::DirKeyKind::BankRedirectType => lower_enum!(BankRedirectType, value),
+
+        dir::DirKeyKind::CryptoType => lower_enum!(CryptoType, value),
+
+        dir::DirKeyKind::PaymentType => lower_enum!(PaymentType, value),
+
+        dir::DirKeyKind::MandateType => lower_enum!(MandateType, value),
+
+        dir::DirKeyKind::MandateAcceptanceType => lower_enum!(MandateAcceptanceType, value),
+
+        dir::DirKeyKind::RewardType => lower_enum!(RewardType, value),
+
+        dir::DirKeyKind::PaymentCurrency => lower_enum!(PaymentCurrency, value),
+
+        dir::DirKeyKind::AuthenticationType => lower_enum!(AuthenticationType, value),
+
+        dir::DirKeyKind::CaptureMethod => lower_enum!(CaptureMethod, value),
+
+        dir::DirKeyKind::BusinessCountry => lower_enum!(BusinessCountry, value),
+
+        dir::DirKeyKind::BillingCountry => lower_enum!(BillingCountry, value),
+
+        dir::DirKeyKind::SetupFutureUsage => lower_enum!(SetupFutureUsage, value),
+
+        dir::DirKeyKind::UpiType => lower_enum!(UpiType, value),
+
+        dir::DirKeyKind::VoucherType => lower_enum!(VoucherType, value),
+
+        dir::DirKeyKind::GiftCardType => lower_enum!(GiftCardType, value),
+
+        dir::DirKeyKind::BankTransferType => lower_enum!(BankTransferType, value),
+
+        dir::DirKeyKind::CardRedirectType => lower_enum!(CardRedirectType, value),
+
+        dir::DirKeyKind::CardBin => {
+            let validation_closure = |st: &String| -> Result<(), AnalysisErrorType> {
+                if st.len() == 6 && st.chars().all(|x| x.is_ascii_digit()) {
+                    Ok(())
+                } else {
+                    Err(AnalysisErrorType::InvalidValue {
+                        key: dir::DirKeyKind::CardBin,
+                        value: st.clone(),
+                        message: Some("Expected 6 digits".to_string()),
+                    })
+                }
+            };
+            lower_str!(CardBin, value, validation_closure)
+        }
+
+        dir::DirKeyKind::BusinessLabel => lower_str!(BusinessLabel, value),
+
+        dir::DirKeyKind::MetaData => lower_metadata!(MetaData, value),
+
+        dir::DirKeyKind::PaymentAmount => lower_number!(PaymentAmount, value, comparison),
+
+        dir::DirKeyKind::Connector => Err(AnalysisErrorType::InvalidKey(
+            dir::DirKeyKind::Connector.to_string(),
+        )),
+    }
+}
+
+/// returns all the comparison values by matching them appropriately to ComparisonTypes and in turn
+/// calls the lower_comparison_inner function
+fn lower_comparison<O: EuclidDirFilter>(
+    comp: ast::Comparison,
+) -> Result<dir::DirComparison, AnalysisError> {
+    let metadata = comp.metadata.clone();
+    let logic = match &comp.comparison {
+        ast::ComparisonType::Equal => dir::DirComparisonLogic::PositiveDisjunction,
+        ast::ComparisonType::NotEqual => dir::DirComparisonLogic::NegativeConjunction,
+        ast::ComparisonType::LessThan => dir::DirComparisonLogic::PositiveDisjunction,
+        ast::ComparisonType::LessThanEqual => dir::DirComparisonLogic::PositiveDisjunction,
+        ast::ComparisonType::GreaterThanEqual => dir::DirComparisonLogic::PositiveDisjunction,
+        ast::ComparisonType::GreaterThan => dir::DirComparisonLogic::PositiveDisjunction,
+    };
+    let values = lower_comparison_inner::<O>(comp).map_err(|etype| AnalysisError {
+        error_type: etype,
+        metadata: metadata.clone(),
+    })?;
+
+    Ok(dir::DirComparison {
+        values,
+        logic,
+        metadata,
+    })
+}
+
+/// lowers the if statement accordingly with a condition and following nested if statements (if
+/// present)
+fn lower_if_statement<O: EuclidDirFilter>(
+    stmt: ast::IfStatement,
+) -> Result<dir::DirIfStatement, AnalysisError> {
+    Ok(dir::DirIfStatement {
+        condition: stmt
+            .condition
+            .into_iter()
+            .map(lower_comparison::<O>)
+            .collect::<Result<_, _>>()?,
+        nested: stmt
+            .nested
+            .map(|n| n.into_iter().map(lower_if_statement::<O>).collect())
+            .transpose()?,
+    })
+}
+
+/// lowers the rules supplied accordingly to DirRule struct by specifying the rule_name,
+/// connector_selection and statements that are a bunch of if statements
+pub fn lower_rule<O: EuclidDirFilter>(
+    rule: ast::Rule<O>,
+) -> Result<dir::DirRule<O>, AnalysisError> {
+    Ok(dir::DirRule {
+        name: rule.name,
+        connector_selection: rule.connector_selection,
+        statements: rule
+            .statements
+            .into_iter()
+            .map(lower_if_statement::<O>)
+            .collect::<Result<_, _>>()?,
+    })
+}
+
+/// uses the above rules and lowers the whole ast Program into DirProgram by specifying
+/// default_selection that is ast ConnectorSelection, a vector of DirRules and clones the metadata
+/// whatever comes in the ast_program
+pub fn lower_program<O: EuclidDirFilter>(
+    program: ast::Program<O>,
+) -> Result<dir::DirProgram<O>, AnalysisError> {
+    Ok(dir::DirProgram {
+        default_selection: program.default_selection,
+        rules: program
+            .rules
+            .into_iter()
+            .map(lower_rule)
+            .collect::<Result<_, _>>()?,
+        metadata: program.metadata,
+    })
+}
diff --git a/crates/euclid/src/frontend/ast/parser.rs b/crates/euclid/src/frontend/ast/parser.rs
new file mode 100644
index 000000000000..8b2f717a8688
--- /dev/null
+++ b/crates/euclid/src/frontend/ast/parser.rs
@@ -0,0 +1,441 @@
+use nom::{
+    branch, bytes::complete, character::complete as pchar, combinator, error, multi, sequence,
+};
+
+use crate::{frontend::ast, types::DummyOutput};
+pub type ParseResult<T, U> = nom::IResult<T, U, nom::error::VerboseError<T>>;
+
+pub enum EuclidError {
+    InvalidPercentage(String),
+    InvalidConnector(String),
+    InvalidOperator(String),
+    InvalidNumber(String),
+}
+
+pub trait EuclidParsable: Sized {
+    fn parse_output(input: &str) -> ParseResult<&str, Self>;
+}
+
+impl EuclidParsable for DummyOutput {
+    fn parse_output(input: &str) -> ParseResult<&str, Self> {
+        let string_w = sequence::delimited(
+            skip_ws(complete::tag("\"")),
+            complete::take_while(|c| c != '"'),
+            skip_ws(complete::tag("\"")),
+        );
+        let full_sequence = multi::many0(sequence::preceded(
+            skip_ws(complete::tag(",")),
+            sequence::delimited(
+                skip_ws(complete::tag("\"")),
+                complete::take_while(|c| c != '"'),
+                skip_ws(complete::tag("\"")),
+            ),
+        ));
+        let sequence = sequence::pair(string_w, full_sequence);
+        error::context(
+            "dummy_strings",
+            combinator::map(
+                sequence::delimited(
+                    skip_ws(complete::tag("[")),
+                    sequence,
+                    skip_ws(complete::tag("]")),
+                ),
+                |out: (&str, Vec<&str>)| {
+                    let mut first = out.1;
+                    first.insert(0, out.0);
+                    let v = first.iter().map(|s| s.to_string()).collect();
+                    Self { outputs: v }
+                },
+            ),
+        )(input)
+    }
+}
+pub fn skip_ws<'a, F: 'a, O>(inner: F) -> impl FnMut(&'a str) -> ParseResult<&str, O>
+where
+    F: FnMut(&'a str) -> ParseResult<&str, O>,
+{
+    sequence::preceded(pchar::multispace0, inner)
+}
+
+pub fn num_i64(input: &str) -> ParseResult<&str, i64> {
+    error::context(
+        "num_i32",
+        combinator::map_res(
+            complete::take_while1(|c: char| c.is_ascii_digit()),
+            |o: &str| {
+                o.parse::<i64>()
+                    .map_err(|_| EuclidError::InvalidNumber(o.to_string()))
+            },
+        ),
+    )(input)
+}
+
+pub fn string_str(input: &str) -> ParseResult<&str, String> {
+    error::context(
+        "String",
+        combinator::map(
+            sequence::delimited(
+                complete::tag("\""),
+                complete::take_while1(|c: char| c != '"'),
+                complete::tag("\""),
+            ),
+            |val: &str| val.to_string(),
+        ),
+    )(input)
+}
+
+pub fn identifier(input: &str) -> ParseResult<&str, String> {
+    error::context(
+        "identifier",
+        combinator::map(
+            sequence::pair(
+                complete::take_while1(|c: char| c.is_ascii_alphabetic() || c == '_'),
+                complete::take_while(|c: char| c.is_ascii_alphanumeric() || c == '_'),
+            ),
+            |out: (&str, &str)| out.0.to_string() + out.1,
+        ),
+    )(input)
+}
+pub fn percentage(input: &str) -> ParseResult<&str, u8> {
+    error::context(
+        "volume_split_percentage",
+        combinator::map_res(
+            sequence::terminated(
+                complete::take_while_m_n(1, 2, |c: char| c.is_ascii_digit()),
+                complete::tag("%"),
+            ),
+            |o: &str| {
+                o.parse::<u8>()
+                    .map_err(|_| EuclidError::InvalidPercentage(o.to_string()))
+            },
+        ),
+    )(input)
+}
+
+pub fn number_value(input: &str) -> ParseResult<&str, ast::ValueType> {
+    error::context(
+        "number_value",
+        combinator::map(num_i64, ast::ValueType::Number),
+    )(input)
+}
+
+pub fn str_value(input: &str) -> ParseResult<&str, ast::ValueType> {
+    error::context(
+        "str_value",
+        combinator::map(string_str, ast::ValueType::StrValue),
+    )(input)
+}
+pub fn enum_value_string(input: &str) -> ParseResult<&str, String> {
+    combinator::map(
+        sequence::pair(
+            complete::take_while1(|c: char| c.is_ascii_alphabetic() || c == '_'),
+            complete::take_while(|c: char| c.is_ascii_alphanumeric() || c == '_'),
+        ),
+        |out: (&str, &str)| out.0.to_string() + out.1,
+    )(input)
+}
+
+pub fn enum_variant_value(input: &str) -> ParseResult<&str, ast::ValueType> {
+    error::context(
+        "enum_variant_value",
+        combinator::map(enum_value_string, ast::ValueType::EnumVariant),
+    )(input)
+}
+
+pub fn number_array_value(input: &str) -> ParseResult<&str, ast::ValueType> {
+    let many_with_comma = multi::many0(sequence::preceded(
+        skip_ws(complete::tag(",")),
+        skip_ws(num_i64),
+    ));
+
+    let full_sequence = sequence::pair(skip_ws(num_i64), many_with_comma);
+
+    error::context(
+        "number_array_value",
+        combinator::map(
+            sequence::delimited(
+                skip_ws(complete::tag("(")),
+                full_sequence,
+                skip_ws(complete::tag(")")),
+            ),
+            |tup: (i64, Vec<i64>)| {
+                let mut rest = tup.1;
+                rest.insert(0, tup.0);
+                ast::ValueType::NumberArray(rest)
+            },
+        ),
+    )(input)
+}
+
+pub fn enum_variant_array_value(input: &str) -> ParseResult<&str, ast::ValueType> {
+    let many_with_comma = multi::many0(sequence::preceded(
+        skip_ws(complete::tag(",")),
+        skip_ws(enum_value_string),
+    ));
+
+    let full_sequence = sequence::pair(skip_ws(enum_value_string), many_with_comma);
+
+    error::context(
+        "enum_variant_array_value",
+        combinator::map(
+            sequence::delimited(
+                skip_ws(complete::tag("(")),
+                full_sequence,
+                skip_ws(complete::tag(")")),
+            ),
+            |tup: (String, Vec<String>)| {
+                let mut rest = tup.1;
+                rest.insert(0, tup.0);
+                ast::ValueType::EnumVariantArray(rest)
+            },
+        ),
+    )(input)
+}
+
+pub fn number_comparison(input: &str) -> ParseResult<&str, ast::NumberComparison> {
+    let operator = combinator::map_res(
+        branch::alt((
+            complete::tag(">="),
+            complete::tag("<="),
+            complete::tag(">"),
+            complete::tag("<"),
+        )),
+        |s: &str| match s {
+            ">=" => Ok(ast::ComparisonType::GreaterThanEqual),
+            "<=" => Ok(ast::ComparisonType::LessThanEqual),
+            ">" => Ok(ast::ComparisonType::GreaterThan),
+            "<" => Ok(ast::ComparisonType::LessThan),
+            _ => Err(EuclidError::InvalidOperator(s.to_string())),
+        },
+    );
+
+    error::context(
+        "number_comparison",
+        combinator::map(
+            sequence::pair(operator, num_i64),
+            |tup: (ast::ComparisonType, i64)| ast::NumberComparison {
+                comparison_type: tup.0,
+                number: tup.1,
+            },
+        ),
+    )(input)
+}
+
+pub fn number_comparison_array_value(input: &str) -> ParseResult<&str, ast::ValueType> {
+    let many_with_comma = multi::many0(sequence::preceded(
+        skip_ws(complete::tag(",")),
+        skip_ws(number_comparison),
+    ));
+
+    let full_sequence = sequence::pair(skip_ws(number_comparison), many_with_comma);
+
+    error::context(
+        "number_comparison_array_value",
+        combinator::map(
+            sequence::delimited(
+                skip_ws(complete::tag("(")),
+                full_sequence,
+                skip_ws(complete::tag(")")),
+            ),
+            |tup: (ast::NumberComparison, Vec<ast::NumberComparison>)| {
+                let mut rest = tup.1;
+                rest.insert(0, tup.0);
+                ast::ValueType::NumberComparisonArray(rest)
+            },
+        ),
+    )(input)
+}
+
+pub fn value_type(input: &str) -> ParseResult<&str, ast::ValueType> {
+    error::context(
+        "value_type",
+        branch::alt((
+            number_value,
+            enum_variant_value,
+            enum_variant_array_value,
+            number_array_value,
+            number_comparison_array_value,
+            str_value,
+        )),
+    )(input)
+}
+
+pub fn comparison_type(input: &str) -> ParseResult<&str, ast::ComparisonType> {
+    error::context(
+        "comparison_operator",
+        combinator::map_res(
+            branch::alt((
+                complete::tag("/="),
+                complete::tag(">="),
+                complete::tag("<="),
+                complete::tag("="),
+                complete::tag(">"),
+                complete::tag("<"),
+            )),
+            |s: &str| match s {
+                "/=" => Ok(ast::ComparisonType::NotEqual),
+                ">=" => Ok(ast::ComparisonType::GreaterThanEqual),
+                "<=" => Ok(ast::ComparisonType::LessThanEqual),
+                "=" => Ok(ast::ComparisonType::Equal),
+                ">" => Ok(ast::ComparisonType::GreaterThan),
+                "<" => Ok(ast::ComparisonType::LessThan),
+                _ => Err(EuclidError::InvalidOperator(s.to_string())),
+            },
+        ),
+    )(input)
+}
+
+pub fn comparison(input: &str) -> ParseResult<&str, ast::Comparison> {
+    error::context(
+        "condition",
+        combinator::map(
+            sequence::tuple((
+                skip_ws(complete::take_while1(|c: char| {
+                    c.is_ascii_alphabetic() || c == '.' || c == '_'
+                })),
+                skip_ws(comparison_type),
+                skip_ws(value_type),
+            )),
+            |tup: (&str, ast::ComparisonType, ast::ValueType)| ast::Comparison {
+                lhs: tup.0.to_string(),
+                comparison: tup.1,
+                value: tup.2,
+                metadata: std::collections::HashMap::new(),
+            },
+        ),
+    )(input)
+}
+
+pub fn arbitrary_comparison(input: &str) -> ParseResult<&str, ast::Comparison> {
+    error::context(
+        "condition",
+        combinator::map(
+            sequence::tuple((
+                skip_ws(string_str),
+                skip_ws(comparison_type),
+                skip_ws(string_str),
+            )),
+            |tup: (String, ast::ComparisonType, String)| ast::Comparison {
+                lhs: "metadata".to_string(),
+                comparison: tup.1,
+                value: ast::ValueType::MetadataVariant(ast::MetadataValue {
+                    key: tup.0,
+                    value: tup.2,
+                }),
+                metadata: std::collections::HashMap::new(),
+            },
+        ),
+    )(input)
+}
+
+pub fn comparison_array(input: &str) -> ParseResult<&str, Vec<ast::Comparison>> {
+    let many_with_ampersand = error::context(
+        "many_with_amp",
+        multi::many0(sequence::preceded(skip_ws(complete::tag("&")), comparison)),
+    );
+
+    let full_sequence = sequence::pair(
+        skip_ws(branch::alt((comparison, arbitrary_comparison))),
+        many_with_ampersand,
+    );
+
+    error::context(
+        "comparison_array",
+        combinator::map(
+            full_sequence,
+            |tup: (ast::Comparison, Vec<ast::Comparison>)| {
+                let mut rest = tup.1;
+                rest.insert(0, tup.0);
+                rest
+            },
+        ),
+    )(input)
+}
+
+pub fn if_statement(input: &str) -> ParseResult<&str, ast::IfStatement> {
+    let nested_block = sequence::delimited(
+        skip_ws(complete::tag("{")),
+        multi::many0(if_statement),
+        skip_ws(complete::tag("}")),
+    );
+
+    error::context(
+        "if_statement",
+        combinator::map(
+            sequence::pair(comparison_array, combinator::opt(nested_block)),
+            |tup: (ast::IfCondition, Option<Vec<ast::IfStatement>>)| ast::IfStatement {
+                condition: tup.0,
+                nested: tup.1,
+            },
+        ),
+    )(input)
+}
+
+pub fn rule_conditions_array(input: &str) -> ParseResult<&str, Vec<ast::IfStatement>> {
+    error::context(
+        "rules_array",
+        sequence::delimited(
+            skip_ws(complete::tag("{")),
+            multi::many1(if_statement),
+            skip_ws(complete::tag("}")),
+        ),
+    )(input)
+}
+
+pub fn rule<O: EuclidParsable>(input: &str) -> ParseResult<&str, ast::Rule<O>> {
+    let rule_name = error::context(
+        "rule_name",
+        combinator::map(
+            skip_ws(sequence::pair(
+                complete::take_while1(|c: char| c.is_ascii_alphabetic() || c == '_'),
+                complete::take_while(|c: char| c.is_ascii_alphanumeric() || c == '_'),
+            )),
+            |out: (&str, &str)| out.0.to_string() + out.1,
+        ),
+    );
+
+    let connector_selection = error::context(
+        "parse_output",
+        sequence::preceded(skip_ws(complete::tag(":")), output),
+    );
+
+    error::context(
+        "rule",
+        combinator::map(
+            sequence::tuple((rule_name, connector_selection, rule_conditions_array)),
+            |tup: (String, O, Vec<ast::IfStatement>)| ast::Rule {
+                name: tup.0,
+                connector_selection: tup.1,
+                statements: tup.2,
+            },
+        ),
+    )(input)
+}
+
+pub fn output<O: EuclidParsable>(input: &str) -> ParseResult<&str, O> {
+    O::parse_output(input)
+}
+
+pub fn default_output<O: EuclidParsable + 'static>(input: &str) -> ParseResult<&str, O> {
+    error::context(
+        "default_output",
+        sequence::preceded(
+            sequence::pair(skip_ws(complete::tag("default")), skip_ws(pchar::char(':'))),
+            skip_ws(output),
+        ),
+    )(input)
+}
+
+pub fn program<O: EuclidParsable + 'static>(input: &str) -> ParseResult<&str, ast::Program<O>> {
+    error::context(
+        "program",
+        combinator::map(
+            sequence::pair(default_output, multi::many1(skip_ws(rule::<O>))),
+            |tup: (O, Vec<ast::Rule<O>>)| ast::Program {
+                default_selection: tup.0,
+                rules: tup.1,
+                metadata: std::collections::HashMap::new(),
+            },
+        ),
+    )(input)
+}
diff --git a/crates/euclid/src/frontend/dir.rs b/crates/euclid/src/frontend/dir.rs
new file mode 100644
index 000000000000..7f2fc252d232
--- /dev/null
+++ b/crates/euclid/src/frontend/dir.rs
@@ -0,0 +1,803 @@
+//! Domain Intermediate Representation
+pub mod enums;
+pub mod lowering;
+pub mod transformers;
+
+use strum::IntoEnumIterator;
+
+use crate::{enums as euclid_enums, frontend::ast, types};
+
+#[macro_export]
+#[cfg(feature = "connector_choice_mca_id")]
+macro_rules! dirval {
+    (Connector = $name:ident) => {
+        $crate::frontend::dir::DirValue::Connector(Box::new(
+            $crate::frontend::ast::ConnectorChoice {
+                connector: $crate::frontend::dir::enums::Connector::$name,
+            },
+        ))
+    };
+
+    ($key:ident = $val:ident) => {{
+        pub use $crate::frontend::dir::enums::*;
+
+        $crate::frontend::dir::DirValue::$key($key::$val)
+    }};
+
+    ($key:ident = $num:literal) => {{
+        $crate::frontend::dir::DirValue::$key($crate::types::NumValue {
+            number: $num,
+            refinement: None,
+        })
+    }};
+
+    ($key:ident s= $str:literal) => {{
+        $crate::frontend::dir::DirValue::$key($crate::types::StrValue {
+            value: $str.to_string(),
+        })
+    }};
+
+    ($key:literal = $str:literal) => {{
+        $crate::frontend::dir::DirValue::MetaData($crate::types::MetadataValue {
+            key: $key.to_string(),
+            value: $str.to_string(),
+        })
+    }};
+}
+
+#[macro_export]
+#[cfg(not(feature = "connector_choice_mca_id"))]
+macro_rules! dirval {
+    (Connector = $name:ident) => {
+        $crate::frontend::dir::DirValue::Connector(Box::new(
+            $crate::frontend::ast::ConnectorChoice {
+                connector: $crate::frontend::dir::enums::Connector::$name,
+                sub_label: None,
+            },
+        ))
+    };
+
+    (Connector = ($name:ident, $sub_label:literal)) => {
+        $crate::frontend::dir::DirValue::Connector(Box::new(
+            $crate::frontend::ast::ConnectorChoice {
+                connector: $crate::frontend::dir::enums::Connector::$name,
+                sub_label: Some($sub_label.to_string()),
+            },
+        ))
+    };
+
+    ($key:ident = $val:ident) => {{
+        pub use $crate::frontend::dir::enums::*;
+
+        $crate::frontend::dir::DirValue::$key($key::$val)
+    }};
+
+    ($key:ident = $num:literal) => {{
+        $crate::frontend::dir::DirValue::$key($crate::types::NumValue {
+            number: $num,
+            refinement: None,
+        })
+    }};
+
+    ($key:ident s= $str:literal) => {{
+        $crate::frontend::dir::DirValue::$key($crate::types::StrValue {
+            value: $str.to_string(),
+        })
+    }};
+    ($key:literal = $str:literal) => {{
+        $crate::frontend::dir::DirValue::MetaData($crate::types::MetadataValue {
+            key: $key.to_string(),
+            value: $str.to_string(),
+        })
+    }};
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize)]
+pub struct DirKey {
+    pub kind: DirKeyKind,
+    pub value: Option<String>,
+}
+
+impl DirKey {
+    pub fn new(kind: DirKeyKind, value: Option<String>) -> Self {
+        Self { kind, value }
+    }
+}
+
+#[derive(
+    Debug,
+    Clone,
+    Hash,
+    PartialEq,
+    Eq,
+    serde::Serialize,
+    strum::Display,
+    strum::EnumIter,
+    strum::EnumVariantNames,
+    strum::EnumString,
+    strum::EnumMessage,
+    strum::EnumProperty,
+)]
+pub enum DirKeyKind {
+    #[strum(
+        serialize = "payment_method",
+        detailed_message = "Different modes of payment - eg. cards, wallets, banks",
+        props(Category = "Payment Methods")
+    )]
+    #[serde(rename = "payment_method")]
+    PaymentMethod,
+    #[strum(
+        serialize = "card_bin",
+        detailed_message = "First 4 to 6 digits of a payment card number",
+        props(Category = "Payment Methods")
+    )]
+    #[serde(rename = "card_bin")]
+    CardBin,
+    #[strum(
+        serialize = "card_type",
+        detailed_message = "Type of the payment card - eg. credit, debit",
+        props(Category = "Payment Methods")
+    )]
+    #[serde(rename = "card_type")]
+    CardType,
+    #[strum(
+        serialize = "card_network",
+        detailed_message = "Network that facilitates payment card transactions",
+        props(Category = "Payment Methods")
+    )]
+    #[serde(rename = "card_network")]
+    CardNetwork,
+    #[strum(
+        serialize = "pay_later",
+        detailed_message = "Supported types of Pay Later payment method",
+        props(Category = "Payment Method Types")
+    )]
+    #[serde(rename = "pay_later")]
+    PayLaterType,
+    #[strum(
+        serialize = "gift_card",
+        detailed_message = "Supported types of Gift Card payment method",
+        props(Category = "Payment Method Types")
+    )]
+    #[serde(rename = "gift_card")]
+    GiftCardType,
+    #[strum(
+        serialize = "mandate_acceptance_type",
+        detailed_message = "Mode of customer acceptance for mandates - online and offline",
+        props(Category = "Payments")
+    )]
+    #[serde(rename = "mandate_acceptance_type")]
+    MandateAcceptanceType,
+    #[strum(
+        serialize = "mandate_type",
+        detailed_message = "Type of mandate acceptance - single use and multi use",
+        props(Category = "Payments")
+    )]
+    #[serde(rename = "mandate_type")]
+    MandateType,
+    #[strum(
+        serialize = "payment_type",
+        detailed_message = "Indicates if a payment is mandate or non-mandate",
+        props(Category = "Payments")
+    )]
+    #[serde(rename = "payment_type")]
+    PaymentType,
+    #[strum(
+        serialize = "wallet",
+        detailed_message = "Supported types of Wallet payment method",
+        props(Category = "Payment Method Types")
+    )]
+    #[serde(rename = "wallet")]
+    WalletType,
+    #[strum(
+        serialize = "upi",
+        detailed_message = "Supported types of UPI payment method",
+        props(Category = "Payment Method Types")
+    )]
+    #[serde(rename = "upi")]
+    UpiType,
+    #[strum(
+        serialize = "voucher",
+        detailed_message = "Supported types of Voucher payment method",
+        props(Category = "Payment Method Types")
+    )]
+    #[serde(rename = "voucher")]
+    VoucherType,
+    #[strum(
+        serialize = "bank_transfer",
+        detailed_message = "Supported types of Bank Transfer payment method",
+        props(Category = "Payment Method Types")
+    )]
+    #[serde(rename = "bank_transfer")]
+    BankTransferType,
+    #[strum(
+        serialize = "bank_redirect",
+        detailed_message = "Supported types of Bank Redirect payment methods",
+        props(Category = "Payment Method Types")
+    )]
+    #[serde(rename = "bank_redirect")]
+    BankRedirectType,
+    #[strum(
+        serialize = "bank_debit",
+        detailed_message = "Supported types of Bank Debit payment method",
+        props(Category = "Payment Method Types")
+    )]
+    #[serde(rename = "bank_debit")]
+    BankDebitType,
+    #[strum(
+        serialize = "crypto",
+        detailed_message = "Supported types of Crypto payment method",
+        props(Category = "Payment Method Types")
+    )]
+    #[serde(rename = "crypto")]
+    CryptoType,
+    #[strum(
+        serialize = "metadata",
+        detailed_message = "Aribitrary Key and value pair",
+        props(Category = "Metadata")
+    )]
+    #[serde(rename = "metadata")]
+    MetaData,
+    #[strum(
+        serialize = "reward",
+        detailed_message = "Supported types of Reward payment method",
+        props(Category = "Payment Method Types")
+    )]
+    #[serde(rename = "reward")]
+    RewardType,
+    #[strum(
+        serialize = "amount",
+        detailed_message = "Value of the transaction",
+        props(Category = "Payments")
+    )]
+    #[serde(rename = "amount")]
+    PaymentAmount,
+    #[strum(
+        serialize = "currency",
+        detailed_message = "Currency used for the payment",
+        props(Category = "Payments")
+    )]
+    #[serde(rename = "currency")]
+    PaymentCurrency,
+    #[strum(
+        serialize = "authentication_type",
+        detailed_message = "Type of authentication for the payment",
+        props(Category = "Payments")
+    )]
+    #[serde(rename = "authentication_type")]
+    AuthenticationType,
+    #[strum(
+        serialize = "capture_method",
+        detailed_message = "Modes of capturing a payment",
+        props(Category = "Payments")
+    )]
+    #[serde(rename = "capture_method")]
+    CaptureMethod,
+    #[strum(
+        serialize = "country",
+        serialize = "business_country",
+        detailed_message = "Country of the business unit",
+        props(Category = "Merchant")
+    )]
+    #[serde(rename = "business_country", alias = "country")]
+    BusinessCountry,
+    #[strum(
+        serialize = "billing_country",
+        detailed_message = "Country of the billing address of the customer",
+        props(Category = "Customer")
+    )]
+    #[serde(rename = "billing_country")]
+    BillingCountry,
+    #[serde(skip_deserializing, rename = "connector")]
+    #[strum(disabled)]
+    Connector,
+    #[strum(
+        serialize = "business_label",
+        detailed_message = "Identifier for business unit",
+        props(Category = "Merchant")
+    )]
+    #[serde(rename = "business_label")]
+    BusinessLabel,
+    #[strum(
+        serialize = "setup_future_usage",
+        detailed_message = "Identifier for recurring payments",
+        props(Category = "Payments")
+    )]
+    #[serde(rename = "setup_future_usage")]
+    SetupFutureUsage,
+    #[strum(
+        serialize = "card_redirect_type",
+        detailed_message = "Supported types of Card Redirect payment method",
+        props(Category = "Payment Method Types")
+    )]
+    #[serde(rename = "card_redirect")]
+    CardRedirectType,
+}
+
+pub trait EuclidDirFilter: Sized
+where
+    Self: 'static,
+{
+    const ALLOWED: &'static [DirKeyKind];
+    fn get_allowed_keys() -> &'static [DirKeyKind] {
+        Self::ALLOWED
+    }
+
+    fn is_key_allowed(key: &DirKeyKind) -> bool {
+        Self::ALLOWED.contains(key)
+    }
+}
+
+impl DirKeyKind {
+    pub fn get_type(&self) -> types::DataType {
+        match self {
+            Self::PaymentMethod => types::DataType::EnumVariant,
+            Self::CardBin => types::DataType::StrValue,
+            Self::CardType => types::DataType::EnumVariant,
+            Self::CardNetwork => types::DataType::EnumVariant,
+            Self::MetaData => types::DataType::MetadataValue,
+            Self::MandateType => types::DataType::EnumVariant,
+            Self::PaymentType => types::DataType::EnumVariant,
+            Self::MandateAcceptanceType => types::DataType::EnumVariant,
+            Self::PayLaterType => types::DataType::EnumVariant,
+            Self::WalletType => types::DataType::EnumVariant,
+            Self::UpiType => types::DataType::EnumVariant,
+            Self::VoucherType => types::DataType::EnumVariant,
+            Self::BankTransferType => types::DataType::EnumVariant,
+            Self::GiftCardType => types::DataType::EnumVariant,
+            Self::BankRedirectType => types::DataType::EnumVariant,
+            Self::CryptoType => types::DataType::EnumVariant,
+            Self::RewardType => types::DataType::EnumVariant,
+            Self::PaymentAmount => types::DataType::Number,
+            Self::PaymentCurrency => types::DataType::EnumVariant,
+            Self::AuthenticationType => types::DataType::EnumVariant,
+            Self::CaptureMethod => types::DataType::EnumVariant,
+            Self::BusinessCountry => types::DataType::EnumVariant,
+            Self::BillingCountry => types::DataType::EnumVariant,
+            Self::Connector => types::DataType::EnumVariant,
+            Self::BankDebitType => types::DataType::EnumVariant,
+            Self::BusinessLabel => types::DataType::StrValue,
+            Self::SetupFutureUsage => types::DataType::EnumVariant,
+            Self::CardRedirectType => types::DataType::EnumVariant,
+        }
+    }
+    pub fn get_value_set(&self) -> Option<Vec<DirValue>> {
+        match self {
+            Self::PaymentMethod => Some(
+                enums::PaymentMethod::iter()
+                    .map(DirValue::PaymentMethod)
+                    .collect(),
+            ),
+            Self::CardBin => None,
+            Self::CardType => Some(enums::CardType::iter().map(DirValue::CardType).collect()),
+            Self::MandateAcceptanceType => Some(
+                euclid_enums::MandateAcceptanceType::iter()
+                    .map(DirValue::MandateAcceptanceType)
+                    .collect(),
+            ),
+            Self::PaymentType => Some(
+                euclid_enums::PaymentType::iter()
+                    .map(DirValue::PaymentType)
+                    .collect(),
+            ),
+            Self::MandateType => Some(
+                euclid_enums::MandateType::iter()
+                    .map(DirValue::MandateType)
+                    .collect(),
+            ),
+            Self::CardNetwork => Some(
+                enums::CardNetwork::iter()
+                    .map(DirValue::CardNetwork)
+                    .collect(),
+            ),
+            Self::PayLaterType => Some(
+                enums::PayLaterType::iter()
+                    .map(DirValue::PayLaterType)
+                    .collect(),
+            ),
+            Self::MetaData => None,
+            Self::WalletType => Some(
+                enums::WalletType::iter()
+                    .map(DirValue::WalletType)
+                    .collect(),
+            ),
+            Self::UpiType => Some(enums::UpiType::iter().map(DirValue::UpiType).collect()),
+            Self::VoucherType => Some(
+                enums::VoucherType::iter()
+                    .map(DirValue::VoucherType)
+                    .collect(),
+            ),
+            Self::BankTransferType => Some(
+                enums::BankTransferType::iter()
+                    .map(DirValue::BankTransferType)
+                    .collect(),
+            ),
+            Self::GiftCardType => Some(
+                enums::GiftCardType::iter()
+                    .map(DirValue::GiftCardType)
+                    .collect(),
+            ),
+            Self::BankRedirectType => Some(
+                enums::BankRedirectType::iter()
+                    .map(DirValue::BankRedirectType)
+                    .collect(),
+            ),
+            Self::CryptoType => Some(
+                enums::CryptoType::iter()
+                    .map(DirValue::CryptoType)
+                    .collect(),
+            ),
+            Self::RewardType => Some(
+                enums::RewardType::iter()
+                    .map(DirValue::RewardType)
+                    .collect(),
+            ),
+            Self::PaymentAmount => None,
+            Self::PaymentCurrency => Some(
+                enums::PaymentCurrency::iter()
+                    .map(DirValue::PaymentCurrency)
+                    .collect(),
+            ),
+            Self::AuthenticationType => Some(
+                enums::AuthenticationType::iter()
+                    .map(DirValue::AuthenticationType)
+                    .collect(),
+            ),
+            Self::CaptureMethod => Some(
+                enums::CaptureMethod::iter()
+                    .map(DirValue::CaptureMethod)
+                    .collect(),
+            ),
+            Self::BankDebitType => Some(
+                enums::BankDebitType::iter()
+                    .map(DirValue::BankDebitType)
+                    .collect(),
+            ),
+            Self::BusinessCountry => Some(
+                enums::Country::iter()
+                    .map(DirValue::BusinessCountry)
+                    .collect(),
+            ),
+            Self::BillingCountry => Some(
+                enums::Country::iter()
+                    .map(DirValue::BillingCountry)
+                    .collect(),
+            ),
+            Self::Connector => Some(
+                enums::Connector::iter()
+                    .map(|connector| {
+                        DirValue::Connector(Box::new(ast::ConnectorChoice {
+                            connector,
+                            #[cfg(not(feature = "connector_choice_mca_id"))]
+                            sub_label: None,
+                        }))
+                    })
+                    .collect(),
+            ),
+            Self::BusinessLabel => None,
+            Self::SetupFutureUsage => Some(
+                enums::SetupFutureUsage::iter()
+                    .map(DirValue::SetupFutureUsage)
+                    .collect(),
+            ),
+            Self::CardRedirectType => Some(
+                enums::CardRedirectType::iter()
+                    .map(DirValue::CardRedirectType)
+                    .collect(),
+            ),
+        }
+    }
+}
+
+#[derive(
+    Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, strum::Display, strum::EnumVariantNames,
+)]
+#[serde(tag = "key", content = "value")]
+pub enum DirValue {
+    #[serde(rename = "payment_method")]
+    PaymentMethod(enums::PaymentMethod),
+    #[serde(rename = "card_bin")]
+    CardBin(types::StrValue),
+    #[serde(rename = "card_type")]
+    CardType(enums::CardType),
+    #[serde(rename = "card_network")]
+    CardNetwork(enums::CardNetwork),
+    #[serde(rename = "metadata")]
+    MetaData(types::MetadataValue),
+    #[serde(rename = "pay_later")]
+    PayLaterType(enums::PayLaterType),
+    #[serde(rename = "wallet")]
+    WalletType(enums::WalletType),
+    #[serde(rename = "acceptance_type")]
+    MandateAcceptanceType(euclid_enums::MandateAcceptanceType),
+    #[serde(rename = "mandate_type")]
+    MandateType(euclid_enums::MandateType),
+    #[serde(rename = "payment_type")]
+    PaymentType(euclid_enums::PaymentType),
+    #[serde(rename = "upi")]
+    UpiType(enums::UpiType),
+    #[serde(rename = "voucher")]
+    VoucherType(enums::VoucherType),
+    #[serde(rename = "bank_transfer")]
+    BankTransferType(enums::BankTransferType),
+    #[serde(rename = "bank_redirect")]
+    BankRedirectType(enums::BankRedirectType),
+    #[serde(rename = "bank_debit")]
+    BankDebitType(enums::BankDebitType),
+    #[serde(rename = "crypto")]
+    CryptoType(enums::CryptoType),
+    #[serde(rename = "reward")]
+    RewardType(enums::RewardType),
+    #[serde(rename = "gift_card")]
+    GiftCardType(enums::GiftCardType),
+    #[serde(rename = "amount")]
+    PaymentAmount(types::NumValue),
+    #[serde(rename = "currency")]
+    PaymentCurrency(enums::PaymentCurrency),
+    #[serde(rename = "authentication_type")]
+    AuthenticationType(enums::AuthenticationType),
+    #[serde(rename = "capture_method")]
+    CaptureMethod(enums::CaptureMethod),
+    #[serde(rename = "business_country", alias = "country")]
+    BusinessCountry(enums::Country),
+    #[serde(rename = "billing_country")]
+    BillingCountry(enums::Country),
+    #[serde(skip_deserializing, rename = "connector")]
+    Connector(Box<ast::ConnectorChoice>),
+    #[serde(rename = "business_label")]
+    BusinessLabel(types::StrValue),
+    #[serde(rename = "setup_future_usage")]
+    SetupFutureUsage(enums::SetupFutureUsage),
+    #[serde(rename = "card_redirect")]
+    CardRedirectType(enums::CardRedirectType),
+}
+
+impl DirValue {
+    pub fn get_key(&self) -> DirKey {
+        let (kind, data) = match self {
+            Self::PaymentMethod(_) => (DirKeyKind::PaymentMethod, None),
+            Self::CardBin(_) => (DirKeyKind::CardBin, None),
+            Self::RewardType(_) => (DirKeyKind::RewardType, None),
+            Self::BusinessCountry(_) => (DirKeyKind::BusinessCountry, None),
+            Self::BillingCountry(_) => (DirKeyKind::CardBin, None),
+            Self::BankTransferType(_) => (DirKeyKind::BankTransferType, None),
+            Self::UpiType(_) => (DirKeyKind::UpiType, None),
+            Self::CardType(_) => (DirKeyKind::CardType, None),
+            Self::CardNetwork(_) => (DirKeyKind::CardNetwork, None),
+            Self::MetaData(met) => (DirKeyKind::MetaData, Some(met.key.clone())),
+            Self::PayLaterType(_) => (DirKeyKind::PayLaterType, None),
+            Self::WalletType(_) => (DirKeyKind::WalletType, None),
+            Self::BankRedirectType(_) => (DirKeyKind::BankRedirectType, None),
+            Self::CryptoType(_) => (DirKeyKind::CryptoType, None),
+            Self::AuthenticationType(_) => (DirKeyKind::AuthenticationType, None),
+            Self::CaptureMethod(_) => (DirKeyKind::CaptureMethod, None),
+            Self::PaymentAmount(_) => (DirKeyKind::PaymentAmount, None),
+            Self::PaymentCurrency(_) => (DirKeyKind::PaymentCurrency, None),
+            Self::Connector(_) => (DirKeyKind::Connector, None),
+            Self::BankDebitType(_) => (DirKeyKind::BankDebitType, None),
+            Self::MandateAcceptanceType(_) => (DirKeyKind::MandateAcceptanceType, None),
+            Self::MandateType(_) => (DirKeyKind::MandateType, None),
+            Self::PaymentType(_) => (DirKeyKind::PaymentType, None),
+            Self::BusinessLabel(_) => (DirKeyKind::BusinessLabel, None),
+            Self::SetupFutureUsage(_) => (DirKeyKind::SetupFutureUsage, None),
+            Self::CardRedirectType(_) => (DirKeyKind::CardRedirectType, None),
+            Self::VoucherType(_) => (DirKeyKind::VoucherType, None),
+            Self::GiftCardType(_) => (DirKeyKind::GiftCardType, None),
+        };
+
+        DirKey::new(kind, data)
+    }
+    pub fn get_metadata_val(&self) -> Option<types::MetadataValue> {
+        match self {
+            Self::MetaData(val) => Some(val.clone()),
+            Self::PaymentMethod(_) => None,
+            Self::CardBin(_) => None,
+            Self::CardType(_) => None,
+            Self::CardNetwork(_) => None,
+            Self::PayLaterType(_) => None,
+            Self::WalletType(_) => None,
+            Self::BankRedirectType(_) => None,
+            Self::CryptoType(_) => None,
+            Self::AuthenticationType(_) => None,
+            Self::CaptureMethod(_) => None,
+            Self::GiftCardType(_) => None,
+            Self::PaymentAmount(_) => None,
+            Self::PaymentCurrency(_) => None,
+            Self::BusinessCountry(_) => None,
+            Self::BillingCountry(_) => None,
+            Self::Connector(_) => None,
+            Self::BankTransferType(_) => None,
+            Self::UpiType(_) => None,
+            Self::BankDebitType(_) => None,
+            Self::RewardType(_) => None,
+            Self::VoucherType(_) => None,
+            Self::MandateAcceptanceType(_) => None,
+            Self::MandateType(_) => None,
+            Self::PaymentType(_) => None,
+            Self::BusinessLabel(_) => None,
+            Self::SetupFutureUsage(_) => None,
+            Self::CardRedirectType(_) => None,
+        }
+    }
+
+    pub fn get_str_val(&self) -> Option<types::StrValue> {
+        match self {
+            Self::CardBin(val) => Some(val.clone()),
+            _ => None,
+        }
+    }
+
+    pub fn get_num_value(&self) -> Option<types::NumValue> {
+        match self {
+            Self::PaymentAmount(val) => Some(val.clone()),
+            _ => None,
+        }
+    }
+
+    pub fn check_equality(v1: &Self, v2: &Self) -> bool {
+        match (v1, v2) {
+            (Self::PaymentMethod(pm1), Self::PaymentMethod(pm2)) => pm1 == pm2,
+            (Self::CardType(ct1), Self::CardType(ct2)) => ct1 == ct2,
+            (Self::CardNetwork(cn1), Self::CardNetwork(cn2)) => cn1 == cn2,
+            (Self::MetaData(md1), Self::MetaData(md2)) => md1 == md2,
+            (Self::PayLaterType(plt1), Self::PayLaterType(plt2)) => plt1 == plt2,
+            (Self::WalletType(wt1), Self::WalletType(wt2)) => wt1 == wt2,
+            (Self::BankDebitType(bdt1), Self::BankDebitType(bdt2)) => bdt1 == bdt2,
+            (Self::BankRedirectType(brt1), Self::BankRedirectType(brt2)) => brt1 == brt2,
+            (Self::BankTransferType(btt1), Self::BankTransferType(btt2)) => btt1 == btt2,
+            (Self::GiftCardType(gct1), Self::GiftCardType(gct2)) => gct1 == gct2,
+            (Self::CryptoType(ct1), Self::CryptoType(ct2)) => ct1 == ct2,
+            (Self::AuthenticationType(at1), Self::AuthenticationType(at2)) => at1 == at2,
+            (Self::CaptureMethod(cm1), Self::CaptureMethod(cm2)) => cm1 == cm2,
+            (Self::PaymentCurrency(pc1), Self::PaymentCurrency(pc2)) => pc1 == pc2,
+            (Self::BusinessCountry(c1), Self::BusinessCountry(c2)) => c1 == c2,
+            (Self::BillingCountry(c1), Self::BillingCountry(c2)) => c1 == c2,
+            (Self::PaymentType(pt1), Self::PaymentType(pt2)) => pt1 == pt2,
+            (Self::MandateType(mt1), Self::MandateType(mt2)) => mt1 == mt2,
+            (Self::MandateAcceptanceType(mat1), Self::MandateAcceptanceType(mat2)) => mat1 == mat2,
+            (Self::RewardType(rt1), Self::RewardType(rt2)) => rt1 == rt2,
+            (Self::Connector(c1), Self::Connector(c2)) => c1 == c2,
+            (Self::BusinessLabel(bl1), Self::BusinessLabel(bl2)) => bl1 == bl2,
+            (Self::SetupFutureUsage(sfu1), Self::SetupFutureUsage(sfu2)) => sfu1 == sfu2,
+            (Self::UpiType(ut1), Self::UpiType(ut2)) => ut1 == ut2,
+            (Self::VoucherType(vt1), Self::VoucherType(vt2)) => vt1 == vt2,
+            (Self::CardRedirectType(crt1), Self::CardRedirectType(crt2)) => crt1 == crt2,
+            _ => false,
+        }
+    }
+}
+
+#[derive(Debug, Clone)]
+pub enum DirComparisonLogic {
+    NegativeConjunction,
+    PositiveDisjunction,
+}
+
+#[derive(Debug, Clone)]
+pub struct DirComparison {
+    pub values: Vec<DirValue>,
+    pub logic: DirComparisonLogic,
+    pub metadata: types::Metadata,
+}
+
+pub type DirIfCondition = Vec<DirComparison>;
+
+#[derive(Debug, Clone)]
+pub struct DirIfStatement {
+    pub condition: DirIfCondition,
+    pub nested: Option<Vec<DirIfStatement>>,
+}
+
+#[derive(Debug, Clone)]
+pub struct DirRule<O> {
+    pub name: String,
+    pub connector_selection: O,
+    pub statements: Vec<DirIfStatement>,
+}
+
+#[derive(Debug, Clone)]
+pub struct DirProgram<O> {
+    pub default_selection: O,
+    pub rules: Vec<DirRule<O>>,
+    pub metadata: types::Metadata,
+}
+
+#[cfg(test)]
+mod test {
+    #![allow(clippy::expect_used)]
+    use rustc_hash::FxHashMap;
+    use strum::IntoEnumIterator;
+
+    use super::*;
+
+    #[test]
+    fn test_consistent_dir_key_naming() {
+        let mut key_names: FxHashMap<DirKeyKind, String> = FxHashMap::default();
+
+        for key in DirKeyKind::iter() {
+            let json_str = if let DirKeyKind::MetaData = key {
+                r#""metadata""#.to_string()
+            } else {
+                serde_json::to_string(&key).expect("JSON Serialization")
+            };
+            let display_str = key.to_string();
+
+            assert_eq!(&json_str[1..json_str.len() - 1], display_str);
+            key_names.insert(key, display_str);
+        }
+
+        let values = vec![
+            dirval!(PaymentMethod = Card),
+            dirval!(CardBin s= "123456"),
+            dirval!(CardType = Credit),
+            dirval!(CardNetwork = Visa),
+            dirval!(PayLaterType = Klarna),
+            dirval!(WalletType = Paypal),
+            dirval!(BankRedirectType = Sofort),
+            dirval!(BankDebitType = Bacs),
+            dirval!(CryptoType = CryptoCurrency),
+            dirval!("" = "metadata"),
+            dirval!(PaymentAmount = 100),
+            dirval!(PaymentCurrency = USD),
+            dirval!(CardRedirectType = Benefit),
+            dirval!(AuthenticationType = ThreeDs),
+            dirval!(CaptureMethod = Manual),
+            dirval!(BillingCountry = UnitedStatesOfAmerica),
+            dirval!(BusinessCountry = France),
+        ];
+
+        for val in values {
+            let json_val = serde_json::to_value(&val).expect("JSON Value Serialization");
+
+            let json_key = json_val
+                .as_object()
+                .expect("Serialized Object")
+                .get("key")
+                .expect("Object Key");
+
+            let value_str = json_key.as_str().expect("Value string");
+            let dir_key = val.get_key();
+
+            let key_name = key_names.get(&dir_key.kind).expect("Key name");
+
+            assert_eq!(key_name, value_str);
+        }
+    }
+
+    #[cfg(feature = "ast_parser")]
+    #[test]
+    fn test_allowed_dir_keys() {
+        use crate::types::DummyOutput;
+
+        let program_str = r#"
+        default: ["stripe", "adyen"]
+
+        rule_1: ["stripe"]
+        {
+           payment_method = card
+        }
+        "#;
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+
+        let out = ast::lowering::lower_program::<DummyOutput>(program);
+        assert!(out.is_ok())
+    }
+    #[cfg(feature = "ast_parser")]
+    #[test]
+    fn test_not_allowed_dir_keys() {
+        use crate::types::DummyOutput;
+
+        let program_str = r#"
+        default: ["stripe", "adyen"]
+
+        rule_1: ["stripe"]
+        {
+           bank_debit = ach
+        }
+        "#;
+        let (_, program) = ast::parser::program::<DummyOutput>(program_str).expect("Program");
+
+        let out = ast::lowering::lower_program::<DummyOutput>(program);
+        assert!(out.is_err())
+    }
+}
diff --git a/crates/euclid/src/frontend/dir/enums.rs b/crates/euclid/src/frontend/dir/enums.rs
new file mode 100644
index 000000000000..17699940363f
--- /dev/null
+++ b/crates/euclid/src/frontend/dir/enums.rs
@@ -0,0 +1,321 @@
+use strum::VariantNames;
+
+use crate::enums::collect_variants;
+pub use crate::enums::{
+    AuthenticationType, CaptureMethod, CardNetwork, Connector, Country, Country as BusinessCountry,
+    Country as BillingCountry, Currency as PaymentCurrency, MandateAcceptanceType, MandateType,
+    PaymentMethod, PaymentType, SetupFutureUsage,
+};
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum CardType {
+    Credit,
+    Debit,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum PayLaterType {
+    Affirm,
+    AfterpayClearpay,
+    Alma,
+    Klarna,
+    PayBright,
+    Walley,
+    Atome,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum WalletType {
+    GooglePay,
+    ApplePay,
+    Paypal,
+    AliPay,
+    AliPayHk,
+    MbWay,
+    MobilePay,
+    WeChatPay,
+    SamsungPay,
+    GoPay,
+    KakaoPay,
+    Twint,
+    Gcash,
+    Vipps,
+    Momo,
+    Dana,
+    TouchNGo,
+    Swish,
+    Cashapp,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum VoucherType {
+    Boleto,
+    Efecty,
+    PagoEfectivo,
+    RedCompra,
+    RedPagos,
+    Alfamart,
+    Indomaret,
+    SevenEleven,
+    Lawson,
+    MiniStop,
+    FamilyMart,
+    Seicomart,
+    PayEasy,
+    Oxxo,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum BankRedirectType {
+    Bizum,
+    Giropay,
+    Ideal,
+    Sofort,
+    Eps,
+    BancontactCard,
+    Blik,
+    Interac,
+    OnlineBankingCzechRepublic,
+    OnlineBankingFinland,
+    OnlineBankingPoland,
+    OnlineBankingSlovakia,
+    OnlineBankingFpx,
+    OnlineBankingThailand,
+    OpenBankingUk,
+    Przelewy24,
+    Trustly,
+}
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum BankTransferType {
+    Multibanco,
+    Ach,
+    Sepa,
+    Bacs,
+    BcaBankTransfer,
+    BniVa,
+    BriVa,
+    CimbVa,
+    DanamonVa,
+    MandiriVa,
+    PermataBankTransfer,
+    Pix,
+    Pse,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum GiftCardType {
+    PaySafeCard,
+    Givex,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum CardRedirectType {
+    Benefit,
+    Knet,
+    MomoAtm,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum CryptoType {
+    CryptoCurrency,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum UpiType {
+    UpiCollect,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum BankDebitType {
+    Ach,
+    Sepa,
+    Bacs,
+    Becs,
+}
+
+#[derive(
+    Clone,
+    Debug,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumIter,
+    strum::EnumString,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum RewardType {
+    ClassicReward,
+    Evoucher,
+}
+
+collect_variants!(CardType);
+collect_variants!(PayLaterType);
+collect_variants!(WalletType);
+collect_variants!(BankRedirectType);
+collect_variants!(BankDebitType);
+collect_variants!(CryptoType);
+collect_variants!(RewardType);
+collect_variants!(UpiType);
+collect_variants!(VoucherType);
+collect_variants!(GiftCardType);
+collect_variants!(BankTransferType);
+collect_variants!(CardRedirectType);
diff --git a/crates/euclid/src/frontend/dir/lowering.rs b/crates/euclid/src/frontend/dir/lowering.rs
new file mode 100644
index 000000000000..516e10e0389e
--- /dev/null
+++ b/crates/euclid/src/frontend/dir/lowering.rs
@@ -0,0 +1,295 @@
+//! Analysis of the lowering logic for the DIR
+//!
+//! Consists of certain functions that supports the lowering logic from DIR to VIR.
+//! These includes the lowering of the DIR program and vector of rules , and the lowering of ifstatements
+//! ,and comparisonsLogic and also the lowering of the enums of value variants from DIR to VIR.
+use super::enums;
+use crate::{
+    dssa::types::{AnalysisError, AnalysisErrorType},
+    enums as global_enums,
+    frontend::{dir, vir},
+    types::EuclidValue,
+};
+
+impl From<enums::CardType> for global_enums::PaymentMethodType {
+    fn from(value: enums::CardType) -> Self {
+        match value {
+            enums::CardType::Credit => Self::Credit,
+            enums::CardType::Debit => Self::Debit,
+        }
+    }
+}
+
+impl From<enums::PayLaterType> for global_enums::PaymentMethodType {
+    fn from(value: enums::PayLaterType) -> Self {
+        match value {
+            enums::PayLaterType::Affirm => Self::Affirm,
+            enums::PayLaterType::AfterpayClearpay => Self::AfterpayClearpay,
+            enums::PayLaterType::Alma => Self::Alma,
+            enums::PayLaterType::Klarna => Self::Klarna,
+            enums::PayLaterType::PayBright => Self::PayBright,
+            enums::PayLaterType::Walley => Self::Walley,
+            enums::PayLaterType::Atome => Self::Atome,
+        }
+    }
+}
+
+impl From<enums::WalletType> for global_enums::PaymentMethodType {
+    fn from(value: enums::WalletType) -> Self {
+        match value {
+            enums::WalletType::GooglePay => Self::GooglePay,
+            enums::WalletType::ApplePay => Self::ApplePay,
+            enums::WalletType::Paypal => Self::Paypal,
+            enums::WalletType::AliPay => Self::AliPay,
+            enums::WalletType::AliPayHk => Self::AliPayHk,
+            enums::WalletType::MbWay => Self::MbWay,
+            enums::WalletType::MobilePay => Self::MobilePay,
+            enums::WalletType::WeChatPay => Self::WeChatPay,
+            enums::WalletType::SamsungPay => Self::SamsungPay,
+            enums::WalletType::GoPay => Self::GoPay,
+            enums::WalletType::KakaoPay => Self::KakaoPay,
+            enums::WalletType::Twint => Self::Twint,
+            enums::WalletType::Gcash => Self::Gcash,
+            enums::WalletType::Vipps => Self::Vipps,
+            enums::WalletType::Momo => Self::Momo,
+            enums::WalletType::Dana => Self::Dana,
+            enums::WalletType::TouchNGo => Self::TouchNGo,
+            enums::WalletType::Swish => Self::Swish,
+            enums::WalletType::Cashapp => Self::Cashapp,
+        }
+    }
+}
+
+impl From<enums::BankDebitType> for global_enums::PaymentMethodType {
+    fn from(value: enums::BankDebitType) -> Self {
+        match value {
+            enums::BankDebitType::Ach => Self::Ach,
+            enums::BankDebitType::Sepa => Self::Sepa,
+            enums::BankDebitType::Bacs => Self::Bacs,
+            enums::BankDebitType::Becs => Self::Becs,
+        }
+    }
+}
+impl From<enums::UpiType> for global_enums::PaymentMethodType {
+    fn from(value: enums::UpiType) -> Self {
+        match value {
+            enums::UpiType::UpiCollect => Self::UpiCollect,
+        }
+    }
+}
+
+impl From<enums::VoucherType> for global_enums::PaymentMethodType {
+    fn from(value: enums::VoucherType) -> Self {
+        match value {
+            enums::VoucherType::Boleto => Self::Boleto,
+            enums::VoucherType::Efecty => Self::Efecty,
+            enums::VoucherType::PagoEfectivo => Self::PagoEfectivo,
+            enums::VoucherType::RedCompra => Self::RedCompra,
+            enums::VoucherType::RedPagos => Self::RedPagos,
+            enums::VoucherType::Alfamart => Self::Alfamart,
+            enums::VoucherType::Indomaret => Self::Indomaret,
+            enums::VoucherType::SevenEleven => Self::SevenEleven,
+            enums::VoucherType::Lawson => Self::Lawson,
+            enums::VoucherType::MiniStop => Self::MiniStop,
+            enums::VoucherType::FamilyMart => Self::FamilyMart,
+            enums::VoucherType::Seicomart => Self::Seicomart,
+            enums::VoucherType::PayEasy => Self::PayEasy,
+            enums::VoucherType::Oxxo => Self::Oxxo,
+        }
+    }
+}
+
+impl From<enums::BankTransferType> for global_enums::PaymentMethodType {
+    fn from(value: enums::BankTransferType) -> Self {
+        match value {
+            enums::BankTransferType::Multibanco => Self::Multibanco,
+            enums::BankTransferType::Pix => Self::Pix,
+            enums::BankTransferType::Pse => Self::Pse,
+            enums::BankTransferType::Ach => Self::Ach,
+            enums::BankTransferType::Sepa => Self::Sepa,
+            enums::BankTransferType::Bacs => Self::Bacs,
+            enums::BankTransferType::BcaBankTransfer => Self::BcaBankTransfer,
+            enums::BankTransferType::BniVa => Self::BniVa,
+            enums::BankTransferType::BriVa => Self::BriVa,
+            enums::BankTransferType::CimbVa => Self::CimbVa,
+            enums::BankTransferType::DanamonVa => Self::DanamonVa,
+            enums::BankTransferType::MandiriVa => Self::MandiriVa,
+            enums::BankTransferType::PermataBankTransfer => Self::PermataBankTransfer,
+        }
+    }
+}
+
+impl From<enums::GiftCardType> for global_enums::PaymentMethodType {
+    fn from(value: enums::GiftCardType) -> Self {
+        match value {
+            enums::GiftCardType::PaySafeCard => Self::PaySafeCard,
+            enums::GiftCardType::Givex => Self::Givex,
+        }
+    }
+}
+
+impl From<enums::CardRedirectType> for global_enums::PaymentMethodType {
+    fn from(value: enums::CardRedirectType) -> Self {
+        match value {
+            enums::CardRedirectType::Benefit => Self::Benefit,
+            enums::CardRedirectType::Knet => Self::Knet,
+            enums::CardRedirectType::MomoAtm => Self::MomoAtm,
+        }
+    }
+}
+
+impl From<enums::BankRedirectType> for global_enums::PaymentMethodType {
+    fn from(value: enums::BankRedirectType) -> Self {
+        match value {
+            enums::BankRedirectType::Bizum => Self::Bizum,
+            enums::BankRedirectType::Giropay => Self::Giropay,
+            enums::BankRedirectType::Ideal => Self::Ideal,
+            enums::BankRedirectType::Sofort => Self::Sofort,
+            enums::BankRedirectType::Eps => Self::Eps,
+            enums::BankRedirectType::BancontactCard => Self::BancontactCard,
+            enums::BankRedirectType::Blik => Self::Blik,
+            enums::BankRedirectType::Interac => Self::Interac,
+            enums::BankRedirectType::OnlineBankingCzechRepublic => Self::OnlineBankingCzechRepublic,
+            enums::BankRedirectType::OnlineBankingFinland => Self::OnlineBankingFinland,
+            enums::BankRedirectType::OnlineBankingPoland => Self::OnlineBankingPoland,
+            enums::BankRedirectType::OnlineBankingSlovakia => Self::OnlineBankingSlovakia,
+            enums::BankRedirectType::OnlineBankingFpx => Self::OnlineBankingFpx,
+            enums::BankRedirectType::OnlineBankingThailand => Self::OnlineBankingThailand,
+            enums::BankRedirectType::OpenBankingUk => Self::OpenBankingUk,
+            enums::BankRedirectType::Przelewy24 => Self::Przelewy24,
+            enums::BankRedirectType::Trustly => Self::Trustly,
+        }
+    }
+}
+
+impl From<enums::CryptoType> for global_enums::PaymentMethodType {
+    fn from(value: enums::CryptoType) -> Self {
+        match value {
+            enums::CryptoType::CryptoCurrency => Self::CryptoCurrency,
+        }
+    }
+}
+
+impl From<enums::RewardType> for global_enums::PaymentMethodType {
+    fn from(value: enums::RewardType) -> Self {
+        match value {
+            enums::RewardType::ClassicReward => Self::ClassicReward,
+            enums::RewardType::Evoucher => Self::Evoucher,
+        }
+    }
+}
+
+/// Analyses of the lowering of the DirValues to EuclidValues .
+///
+/// For example,
+/// ```notrust
+/// DirValue::PaymentMethod::Cards -> EuclidValue::PaymentMethod::Cards
+/// ```notrust
+/// This is a function that lowers the Values of the DIR variants into the Value of the VIR variants.
+/// The function for each DirValue variant creates a corresponding EuclidValue variants and if there
+/// lacks any direct mapping, it return an Error.
+fn lower_value(dir_value: dir::DirValue) -> Result<EuclidValue, AnalysisErrorType> {
+    Ok(match dir_value {
+        dir::DirValue::PaymentMethod(pm) => EuclidValue::PaymentMethod(pm),
+        dir::DirValue::CardBin(ci) => EuclidValue::CardBin(ci),
+        dir::DirValue::CardType(ct) => EuclidValue::PaymentMethodType(ct.into()),
+        dir::DirValue::CardNetwork(cn) => EuclidValue::CardNetwork(cn),
+        dir::DirValue::MetaData(md) => EuclidValue::Metadata(md),
+        dir::DirValue::PayLaterType(plt) => EuclidValue::PaymentMethodType(plt.into()),
+        dir::DirValue::WalletType(wt) => EuclidValue::PaymentMethodType(wt.into()),
+        dir::DirValue::UpiType(ut) => EuclidValue::PaymentMethodType(ut.into()),
+        dir::DirValue::VoucherType(vt) => EuclidValue::PaymentMethodType(vt.into()),
+        dir::DirValue::BankTransferType(btt) => EuclidValue::PaymentMethodType(btt.into()),
+        dir::DirValue::GiftCardType(gct) => EuclidValue::PaymentMethodType(gct.into()),
+        dir::DirValue::CardRedirectType(crt) => EuclidValue::PaymentMethodType(crt.into()),
+        dir::DirValue::BankRedirectType(brt) => EuclidValue::PaymentMethodType(brt.into()),
+        dir::DirValue::CryptoType(ct) => EuclidValue::PaymentMethodType(ct.into()),
+        dir::DirValue::AuthenticationType(at) => EuclidValue::AuthenticationType(at),
+        dir::DirValue::CaptureMethod(cm) => EuclidValue::CaptureMethod(cm),
+        dir::DirValue::PaymentAmount(pa) => EuclidValue::PaymentAmount(pa),
+        dir::DirValue::PaymentCurrency(pc) => EuclidValue::PaymentCurrency(pc),
+        dir::DirValue::BusinessCountry(buc) => EuclidValue::BusinessCountry(buc),
+        dir::DirValue::BillingCountry(bic) => EuclidValue::BillingCountry(bic),
+        dir::DirValue::MandateAcceptanceType(mat) => EuclidValue::MandateAcceptanceType(mat),
+        dir::DirValue::MandateType(mt) => EuclidValue::MandateType(mt),
+        dir::DirValue::PaymentType(pt) => EuclidValue::PaymentType(pt),
+        dir::DirValue::Connector(_) => Err(AnalysisErrorType::UnsupportedProgramKey(
+            dir::DirKeyKind::Connector,
+        ))?,
+        dir::DirValue::BankDebitType(bdt) => EuclidValue::PaymentMethodType(bdt.into()),
+        dir::DirValue::RewardType(rt) => EuclidValue::PaymentMethodType(rt.into()),
+        dir::DirValue::BusinessLabel(bl) => EuclidValue::BusinessLabel(bl),
+        dir::DirValue::SetupFutureUsage(sfu) => EuclidValue::SetupFutureUsage(sfu),
+    })
+}
+
+fn lower_comparison(
+    dir_comparison: dir::DirComparison,
+) -> Result<vir::ValuedComparison, AnalysisErrorType> {
+    Ok(vir::ValuedComparison {
+        values: dir_comparison
+            .values
+            .into_iter()
+            .map(lower_value)
+            .collect::<Result<_, _>>()?,
+        logic: match dir_comparison.logic {
+            dir::DirComparisonLogic::NegativeConjunction => {
+                vir::ValuedComparisonLogic::NegativeConjunction
+            }
+            dir::DirComparisonLogic::PositiveDisjunction => {
+                vir::ValuedComparisonLogic::PositiveDisjunction
+            }
+        },
+        metadata: dir_comparison.metadata,
+    })
+}
+
+fn lower_if_statement(
+    dir_if_statement: dir::DirIfStatement,
+) -> Result<vir::ValuedIfStatement, AnalysisErrorType> {
+    Ok(vir::ValuedIfStatement {
+        condition: dir_if_statement
+            .condition
+            .into_iter()
+            .map(lower_comparison)
+            .collect::<Result<_, _>>()?,
+        nested: dir_if_statement
+            .nested
+            .map(|v| {
+                v.into_iter()
+                    .map(lower_if_statement)
+                    .collect::<Result<_, _>>()
+            })
+            .transpose()?,
+    })
+}
+
+fn lower_rule<O>(dir_rule: dir::DirRule<O>) -> Result<vir::ValuedRule<O>, AnalysisErrorType> {
+    Ok(vir::ValuedRule {
+        name: dir_rule.name,
+        connector_selection: dir_rule.connector_selection,
+        statements: dir_rule
+            .statements
+            .into_iter()
+            .map(lower_if_statement)
+            .collect::<Result<_, _>>()?,
+    })
+}
+
+pub fn lower_program<O>(
+    dir_program: dir::DirProgram<O>,
+) -> Result<vir::ValuedProgram<O>, AnalysisError> {
+    Ok(vir::ValuedProgram {
+        default_selection: dir_program.default_selection,
+        rules: dir_program
+            .rules
+            .into_iter()
+            .map(lower_rule)
+            .collect::<Result<_, _>>()
+            .map_err(|e| AnalysisError {
+                error_type: e,
+                metadata: Default::default(),
+            })?,
+        metadata: dir_program.metadata,
+    })
+}
diff --git a/crates/euclid/src/frontend/dir/transformers.rs b/crates/euclid/src/frontend/dir/transformers.rs
new file mode 100644
index 000000000000..da413d380c0f
--- /dev/null
+++ b/crates/euclid/src/frontend/dir/transformers.rs
@@ -0,0 +1,166 @@
+use crate::{dirval, dssa::types::AnalysisErrorType, enums as global_enums, frontend::dir};
+
+pub trait IntoDirValue {
+    fn into_dir_value(self) -> Result<dir::DirValue, AnalysisErrorType>;
+}
+impl IntoDirValue for (global_enums::PaymentMethodType, global_enums::PaymentMethod) {
+    fn into_dir_value(self) -> Result<dir::DirValue, AnalysisErrorType> {
+        match self.0 {
+            global_enums::PaymentMethodType::Credit => Ok(dirval!(CardType = Credit)),
+            global_enums::PaymentMethodType::Debit => Ok(dirval!(CardType = Debit)),
+            global_enums::PaymentMethodType::Giropay => Ok(dirval!(BankRedirectType = Giropay)),
+            global_enums::PaymentMethodType::Ideal => Ok(dirval!(BankRedirectType = Ideal)),
+            global_enums::PaymentMethodType::Sofort => Ok(dirval!(BankRedirectType = Sofort)),
+            global_enums::PaymentMethodType::Eps => Ok(dirval!(BankRedirectType = Eps)),
+            global_enums::PaymentMethodType::Klarna => Ok(dirval!(PayLaterType = Klarna)),
+            global_enums::PaymentMethodType::Affirm => Ok(dirval!(PayLaterType = Affirm)),
+            global_enums::PaymentMethodType::AfterpayClearpay => {
+                Ok(dirval!(PayLaterType = AfterpayClearpay))
+            }
+            global_enums::PaymentMethodType::GooglePay => Ok(dirval!(WalletType = GooglePay)),
+            global_enums::PaymentMethodType::ApplePay => Ok(dirval!(WalletType = ApplePay)),
+            global_enums::PaymentMethodType::Paypal => Ok(dirval!(WalletType = Paypal)),
+            global_enums::PaymentMethodType::CryptoCurrency => {
+                Ok(dirval!(CryptoType = CryptoCurrency))
+            }
+            global_enums::PaymentMethodType::Ach => match self.1 {
+                global_enums::PaymentMethod::BankDebit => Ok(dirval!(BankDebitType = Ach)),
+                global_enums::PaymentMethod::BankTransfer => Ok(dirval!(BankTransferType = Ach)),
+                global_enums::PaymentMethod::PayLater
+                | global_enums::PaymentMethod::Card
+                | global_enums::PaymentMethod::CardRedirect
+                | global_enums::PaymentMethod::Wallet
+                | global_enums::PaymentMethod::BankRedirect
+                | global_enums::PaymentMethod::Crypto
+                | global_enums::PaymentMethod::Reward
+                | global_enums::PaymentMethod::Upi
+                | global_enums::PaymentMethod::Voucher
+                | global_enums::PaymentMethod::GiftCard => Err(AnalysisErrorType::NotSupported),
+            },
+            global_enums::PaymentMethodType::Bacs => match self.1 {
+                global_enums::PaymentMethod::BankDebit => Ok(dirval!(BankDebitType = Bacs)),
+                global_enums::PaymentMethod::BankTransfer => Ok(dirval!(BankTransferType = Bacs)),
+                global_enums::PaymentMethod::PayLater
+                | global_enums::PaymentMethod::Card
+                | global_enums::PaymentMethod::CardRedirect
+                | global_enums::PaymentMethod::Wallet
+                | global_enums::PaymentMethod::BankRedirect
+                | global_enums::PaymentMethod::Crypto
+                | global_enums::PaymentMethod::Reward
+                | global_enums::PaymentMethod::Upi
+                | global_enums::PaymentMethod::Voucher
+                | global_enums::PaymentMethod::GiftCard => Err(AnalysisErrorType::NotSupported),
+            },
+            global_enums::PaymentMethodType::Becs => Ok(dirval!(BankDebitType = Becs)),
+            global_enums::PaymentMethodType::Sepa => match self.1 {
+                global_enums::PaymentMethod::BankDebit => Ok(dirval!(BankDebitType = Sepa)),
+                global_enums::PaymentMethod::BankTransfer => Ok(dirval!(BankTransferType = Sepa)),
+                global_enums::PaymentMethod::PayLater
+                | global_enums::PaymentMethod::Card
+                | global_enums::PaymentMethod::CardRedirect
+                | global_enums::PaymentMethod::Wallet
+                | global_enums::PaymentMethod::BankRedirect
+                | global_enums::PaymentMethod::Crypto
+                | global_enums::PaymentMethod::Reward
+                | global_enums::PaymentMethod::Upi
+                | global_enums::PaymentMethod::Voucher
+                | global_enums::PaymentMethod::GiftCard => Err(AnalysisErrorType::NotSupported),
+            },
+            global_enums::PaymentMethodType::AliPay => Ok(dirval!(WalletType = AliPay)),
+            global_enums::PaymentMethodType::AliPayHk => Ok(dirval!(WalletType = AliPayHk)),
+            global_enums::PaymentMethodType::BancontactCard => {
+                Ok(dirval!(BankRedirectType = BancontactCard))
+            }
+            global_enums::PaymentMethodType::Blik => Ok(dirval!(BankRedirectType = Blik)),
+            global_enums::PaymentMethodType::MbWay => Ok(dirval!(WalletType = MbWay)),
+            global_enums::PaymentMethodType::MobilePay => Ok(dirval!(WalletType = MobilePay)),
+            global_enums::PaymentMethodType::Cashapp => Ok(dirval!(WalletType = Cashapp)),
+            global_enums::PaymentMethodType::Multibanco => {
+                Ok(dirval!(BankTransferType = Multibanco))
+            }
+            global_enums::PaymentMethodType::Pix => Ok(dirval!(BankTransferType = Pix)),
+            global_enums::PaymentMethodType::Pse => Ok(dirval!(BankTransferType = Pse)),
+            global_enums::PaymentMethodType::Interac => Ok(dirval!(BankRedirectType = Interac)),
+            global_enums::PaymentMethodType::OnlineBankingCzechRepublic => {
+                Ok(dirval!(BankRedirectType = OnlineBankingCzechRepublic))
+            }
+            global_enums::PaymentMethodType::OnlineBankingFinland => {
+                Ok(dirval!(BankRedirectType = OnlineBankingFinland))
+            }
+            global_enums::PaymentMethodType::OnlineBankingPoland => {
+                Ok(dirval!(BankRedirectType = OnlineBankingPoland))
+            }
+            global_enums::PaymentMethodType::OnlineBankingSlovakia => {
+                Ok(dirval!(BankRedirectType = OnlineBankingSlovakia))
+            }
+            global_enums::PaymentMethodType::Swish => Ok(dirval!(WalletType = Swish)),
+            global_enums::PaymentMethodType::Trustly => Ok(dirval!(BankRedirectType = Trustly)),
+            global_enums::PaymentMethodType::Bizum => Ok(dirval!(BankRedirectType = Bizum)),
+
+            global_enums::PaymentMethodType::PayBright => Ok(dirval!(PayLaterType = PayBright)),
+            global_enums::PaymentMethodType::Walley => Ok(dirval!(PayLaterType = Walley)),
+            global_enums::PaymentMethodType::Przelewy24 => {
+                Ok(dirval!(BankRedirectType = Przelewy24))
+            }
+            global_enums::PaymentMethodType::WeChatPay => Ok(dirval!(WalletType = WeChatPay)),
+
+            global_enums::PaymentMethodType::ClassicReward => {
+                Ok(dirval!(RewardType = ClassicReward))
+            }
+            global_enums::PaymentMethodType::Evoucher => Ok(dirval!(RewardType = Evoucher)),
+            global_enums::PaymentMethodType::UpiCollect => Ok(dirval!(UpiType = UpiCollect)),
+            global_enums::PaymentMethodType::SamsungPay => Ok(dirval!(WalletType = SamsungPay)),
+            global_enums::PaymentMethodType::GoPay => Ok(dirval!(WalletType = GoPay)),
+            global_enums::PaymentMethodType::KakaoPay => Ok(dirval!(WalletType = KakaoPay)),
+            global_enums::PaymentMethodType::Twint => Ok(dirval!(WalletType = Twint)),
+            global_enums::PaymentMethodType::Gcash => Ok(dirval!(WalletType = Gcash)),
+            global_enums::PaymentMethodType::Vipps => Ok(dirval!(WalletType = Vipps)),
+            global_enums::PaymentMethodType::Momo => Ok(dirval!(WalletType = Momo)),
+            global_enums::PaymentMethodType::Alma => Ok(dirval!(PayLaterType = Alma)),
+            global_enums::PaymentMethodType::Dana => Ok(dirval!(WalletType = Dana)),
+            global_enums::PaymentMethodType::OnlineBankingFpx => {
+                Ok(dirval!(BankRedirectType = OnlineBankingFpx))
+            }
+            global_enums::PaymentMethodType::OnlineBankingThailand => {
+                Ok(dirval!(BankRedirectType = OnlineBankingThailand))
+            }
+            global_enums::PaymentMethodType::TouchNGo => Ok(dirval!(WalletType = TouchNGo)),
+            global_enums::PaymentMethodType::Atome => Ok(dirval!(PayLaterType = Atome)),
+            global_enums::PaymentMethodType::Boleto => Ok(dirval!(VoucherType = Boleto)),
+            global_enums::PaymentMethodType::Efecty => Ok(dirval!(VoucherType = Efecty)),
+            global_enums::PaymentMethodType::PagoEfectivo => {
+                Ok(dirval!(VoucherType = PagoEfectivo))
+            }
+            global_enums::PaymentMethodType::RedCompra => Ok(dirval!(VoucherType = RedCompra)),
+            global_enums::PaymentMethodType::RedPagos => Ok(dirval!(VoucherType = RedPagos)),
+            global_enums::PaymentMethodType::Alfamart => Ok(dirval!(VoucherType = Alfamart)),
+            global_enums::PaymentMethodType::BcaBankTransfer => {
+                Ok(dirval!(BankTransferType = BcaBankTransfer))
+            }
+            global_enums::PaymentMethodType::BniVa => Ok(dirval!(BankTransferType = BniVa)),
+            global_enums::PaymentMethodType::BriVa => Ok(dirval!(BankTransferType = BriVa)),
+            global_enums::PaymentMethodType::CimbVa => Ok(dirval!(BankTransferType = CimbVa)),
+            global_enums::PaymentMethodType::DanamonVa => Ok(dirval!(BankTransferType = DanamonVa)),
+            global_enums::PaymentMethodType::Indomaret => Ok(dirval!(VoucherType = Indomaret)),
+            global_enums::PaymentMethodType::MandiriVa => Ok(dirval!(BankTransferType = MandiriVa)),
+            global_enums::PaymentMethodType::PermataBankTransfer => {
+                Ok(dirval!(BankTransferType = PermataBankTransfer))
+            }
+            global_enums::PaymentMethodType::PaySafeCard => Ok(dirval!(GiftCardType = PaySafeCard)),
+            global_enums::PaymentMethodType::SevenEleven => Ok(dirval!(VoucherType = SevenEleven)),
+            global_enums::PaymentMethodType::Lawson => Ok(dirval!(VoucherType = Lawson)),
+            global_enums::PaymentMethodType::MiniStop => Ok(dirval!(VoucherType = MiniStop)),
+            global_enums::PaymentMethodType::FamilyMart => Ok(dirval!(VoucherType = FamilyMart)),
+            global_enums::PaymentMethodType::Seicomart => Ok(dirval!(VoucherType = Seicomart)),
+            global_enums::PaymentMethodType::PayEasy => Ok(dirval!(VoucherType = PayEasy)),
+            global_enums::PaymentMethodType::Givex => Ok(dirval!(GiftCardType = Givex)),
+            global_enums::PaymentMethodType::Benefit => Ok(dirval!(CardRedirectType = Benefit)),
+            global_enums::PaymentMethodType::Knet => Ok(dirval!(CardRedirectType = Knet)),
+            global_enums::PaymentMethodType::OpenBankingUk => {
+                Ok(dirval!(BankRedirectType = OpenBankingUk))
+            }
+            global_enums::PaymentMethodType::MomoAtm => Ok(dirval!(CardRedirectType = MomoAtm)),
+            global_enums::PaymentMethodType::Oxxo => Ok(dirval!(VoucherType = Oxxo)),
+        }
+    }
+}
diff --git a/crates/euclid/src/frontend/vir.rs b/crates/euclid/src/frontend/vir.rs
new file mode 100644
index 000000000000..750ff4e61ff8
--- /dev/null
+++ b/crates/euclid/src/frontend/vir.rs
@@ -0,0 +1,37 @@
+//! Valued Intermediate Representation
+use crate::types::{EuclidValue, Metadata};
+
+#[derive(Debug, Clone)]
+pub enum ValuedComparisonLogic {
+    NegativeConjunction,
+    PositiveDisjunction,
+}
+
+#[derive(Clone, Debug)]
+pub struct ValuedComparison {
+    pub values: Vec<EuclidValue>,
+    pub logic: ValuedComparisonLogic,
+    pub metadata: Metadata,
+}
+
+pub type ValuedIfCondition = Vec<ValuedComparison>;
+
+#[derive(Clone, Debug)]
+pub struct ValuedIfStatement {
+    pub condition: ValuedIfCondition,
+    pub nested: Option<Vec<ValuedIfStatement>>,
+}
+
+#[derive(Clone, Debug)]
+pub struct ValuedRule<O> {
+    pub name: String,
+    pub connector_selection: O,
+    pub statements: Vec<ValuedIfStatement>,
+}
+
+#[derive(Clone, Debug)]
+pub struct ValuedProgram<O> {
+    pub default_selection: O,
+    pub rules: Vec<ValuedRule<O>>,
+    pub metadata: Metadata,
+}
diff --git a/crates/euclid/src/lib.rs b/crates/euclid/src/lib.rs
new file mode 100644
index 000000000000..d64297437aeb
--- /dev/null
+++ b/crates/euclid/src/lib.rs
@@ -0,0 +1,7 @@
+#![allow(clippy::result_large_err)]
+pub mod backend;
+pub mod dssa;
+pub mod enums;
+pub mod frontend;
+pub mod types;
+pub mod utils;
diff --git a/crates/euclid/src/types.rs b/crates/euclid/src/types.rs
new file mode 100644
index 000000000000..59736ae65125
--- /dev/null
+++ b/crates/euclid/src/types.rs
@@ -0,0 +1,318 @@
+pub mod transformers;
+
+use euclid_macros::EnumNums;
+use serde::Serialize;
+use strum::VariantNames;
+
+use crate::{
+    dssa::types::EuclidAnalysable,
+    enums,
+    frontend::{
+        ast,
+        dir::{DirKeyKind, DirValue, EuclidDirFilter},
+    },
+};
+
+pub type Metadata = std::collections::HashMap<String, serde_json::Value>;
+
+#[derive(
+    Debug,
+    Clone,
+    EnumNums,
+    Hash,
+    PartialEq,
+    Eq,
+    strum::Display,
+    strum::EnumVariantNames,
+    strum::EnumString,
+)]
+pub enum EuclidKey {
+    #[strum(serialize = "payment_method")]
+    PaymentMethod,
+    #[strum(serialize = "card_bin")]
+    CardBin,
+    #[strum(serialize = "metadata")]
+    Metadata,
+    #[strum(serialize = "mandate_type")]
+    MandateType,
+    #[strum(serialize = "mandate_acceptance_type")]
+    MandateAcceptanceType,
+    #[strum(serialize = "payment_type")]
+    PaymentType,
+    #[strum(serialize = "payment_method_type")]
+    PaymentMethodType,
+    #[strum(serialize = "card_network")]
+    CardNetwork,
+    #[strum(serialize = "authentication_type")]
+    AuthenticationType,
+    #[strum(serialize = "capture_method")]
+    CaptureMethod,
+    #[strum(serialize = "amount")]
+    PaymentAmount,
+    #[strum(serialize = "currency")]
+    PaymentCurrency,
+    #[strum(serialize = "country", to_string = "business_country")]
+    BusinessCountry,
+    #[strum(serialize = "billing_country")]
+    BillingCountry,
+    #[strum(serialize = "business_label")]
+    BusinessLabel,
+    #[strum(serialize = "setup_future_usage")]
+    SetupFutureUsage,
+}
+impl EuclidDirFilter for DummyOutput {
+    const ALLOWED: &'static [DirKeyKind] = &[
+        DirKeyKind::AuthenticationType,
+        DirKeyKind::PaymentMethod,
+        DirKeyKind::CardType,
+        DirKeyKind::PaymentCurrency,
+        DirKeyKind::CaptureMethod,
+        DirKeyKind::AuthenticationType,
+        DirKeyKind::CardBin,
+        DirKeyKind::PayLaterType,
+        DirKeyKind::PaymentAmount,
+        DirKeyKind::MetaData,
+        DirKeyKind::MandateAcceptanceType,
+        DirKeyKind::MandateType,
+        DirKeyKind::PaymentType,
+        DirKeyKind::SetupFutureUsage,
+    ];
+}
+impl EuclidAnalysable for DummyOutput {
+    fn get_dir_value_for_analysis(&self, rule_name: String) -> Vec<(DirValue, Metadata)> {
+        self.outputs
+            .iter()
+            .map(|dummyc| {
+                let metadata_key = "MetadataKey".to_string();
+                let metadata_value = dummyc;
+                (
+                    DirValue::MetaData(MetadataValue {
+                        key: metadata_key.clone(),
+                        value: metadata_value.clone(),
+                    }),
+                    std::collections::HashMap::from_iter([(
+                        "DUMMY_OUTPUT".to_string(),
+                        serde_json::json!({
+                            "rule_name":rule_name,
+                             "Metadata_Key" :metadata_key,
+                             "Metadata_Value" : metadata_value,
+                        }),
+                    )]),
+                )
+            })
+            .collect()
+    }
+}
+#[derive(Debug, Clone, Serialize)]
+pub struct DummyOutput {
+    pub outputs: Vec<String>,
+}
+
+#[derive(Debug, Clone, serde::Serialize, strum::Display)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum DataType {
+    Number,
+    EnumVariant,
+    MetadataValue,
+    StrValue,
+}
+
+impl EuclidKey {
+    pub fn key_type(&self) -> DataType {
+        match self {
+            Self::PaymentMethod => DataType::EnumVariant,
+            Self::CardBin => DataType::StrValue,
+            Self::Metadata => DataType::MetadataValue,
+            Self::PaymentMethodType => DataType::EnumVariant,
+            Self::CardNetwork => DataType::EnumVariant,
+            Self::AuthenticationType => DataType::EnumVariant,
+            Self::CaptureMethod => DataType::EnumVariant,
+            Self::PaymentAmount => DataType::Number,
+            Self::PaymentCurrency => DataType::EnumVariant,
+            Self::BusinessCountry => DataType::EnumVariant,
+            Self::BillingCountry => DataType::EnumVariant,
+            Self::MandateType => DataType::EnumVariant,
+            Self::MandateAcceptanceType => DataType::EnumVariant,
+            Self::PaymentType => DataType::EnumVariant,
+            Self::BusinessLabel => DataType::StrValue,
+            Self::SetupFutureUsage => DataType::EnumVariant,
+        }
+    }
+}
+
+enums::collect_variants!(EuclidKey);
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize)]
+#[serde(rename_all = "snake_case")]
+pub enum NumValueRefinement {
+    NotEqual,
+    GreaterThan,
+    LessThan,
+    GreaterThanEqual,
+    LessThanEqual,
+}
+
+impl From<ast::ComparisonType> for Option<NumValueRefinement> {
+    fn from(comp_type: ast::ComparisonType) -> Self {
+        match comp_type {
+            ast::ComparisonType::Equal => None,
+            ast::ComparisonType::NotEqual => Some(NumValueRefinement::NotEqual),
+            ast::ComparisonType::GreaterThan => Some(NumValueRefinement::GreaterThan),
+            ast::ComparisonType::LessThan => Some(NumValueRefinement::LessThan),
+            ast::ComparisonType::LessThanEqual => Some(NumValueRefinement::LessThanEqual),
+            ast::ComparisonType::GreaterThanEqual => Some(NumValueRefinement::GreaterThanEqual),
+        }
+    }
+}
+
+impl From<NumValueRefinement> for ast::ComparisonType {
+    fn from(value: NumValueRefinement) -> Self {
+        match value {
+            NumValueRefinement::NotEqual => Self::NotEqual,
+            NumValueRefinement::LessThan => Self::LessThan,
+            NumValueRefinement::GreaterThan => Self::GreaterThan,
+            NumValueRefinement::GreaterThanEqual => Self::GreaterThanEqual,
+            NumValueRefinement::LessThanEqual => Self::LessThanEqual,
+        }
+    }
+}
+
+#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, serde::Serialize)]
+pub struct StrValue {
+    pub value: String,
+}
+
+#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, serde::Serialize)]
+pub struct MetadataValue {
+    pub key: String,
+    pub value: String,
+}
+
+#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, serde::Serialize)]
+pub struct NumValue {
+    pub number: i64,
+    pub refinement: Option<NumValueRefinement>,
+}
+
+impl NumValue {
+    pub fn fits(&self, other: &Self) -> bool {
+        let this_num = self.number;
+        let other_num = other.number;
+
+        match (&self.refinement, &other.refinement) {
+            (None, None) => this_num == other_num,
+
+            (Some(NumValueRefinement::GreaterThan), None) => other_num > this_num,
+
+            (Some(NumValueRefinement::LessThan), None) => other_num < this_num,
+
+            (Some(NumValueRefinement::NotEqual), Some(NumValueRefinement::NotEqual)) => {
+                other_num == this_num
+            }
+
+            (Some(NumValueRefinement::GreaterThan), Some(NumValueRefinement::GreaterThan)) => {
+                other_num > this_num
+            }
+            (Some(NumValueRefinement::LessThan), Some(NumValueRefinement::LessThan)) => {
+                other_num < this_num
+            }
+
+            (Some(NumValueRefinement::GreaterThanEqual), None) => other_num >= this_num,
+            (Some(NumValueRefinement::LessThanEqual), None) => other_num <= this_num,
+            (
+                Some(NumValueRefinement::GreaterThanEqual),
+                Some(NumValueRefinement::GreaterThanEqual),
+            ) => other_num >= this_num,
+
+            (Some(NumValueRefinement::LessThanEqual), Some(NumValueRefinement::LessThanEqual)) => {
+                other_num <= this_num
+            }
+
+            _ => false,
+        }
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum EuclidValue {
+    PaymentMethod(enums::PaymentMethod),
+    CardBin(StrValue),
+    Metadata(MetadataValue),
+    PaymentMethodType(enums::PaymentMethodType),
+    CardNetwork(enums::CardNetwork),
+    AuthenticationType(enums::AuthenticationType),
+    CaptureMethod(enums::CaptureMethod),
+    PaymentType(enums::PaymentType),
+    MandateAcceptanceType(enums::MandateAcceptanceType),
+    MandateType(enums::MandateType),
+    PaymentAmount(NumValue),
+    PaymentCurrency(enums::Currency),
+    BusinessCountry(enums::Country),
+    BillingCountry(enums::Country),
+    BusinessLabel(StrValue),
+    SetupFutureUsage(enums::SetupFutureUsage),
+}
+
+impl EuclidValue {
+    pub fn get_num_value(&self) -> Option<NumValue> {
+        match self {
+            Self::PaymentAmount(val) => Some(val.clone()),
+            _ => None,
+        }
+    }
+
+    pub fn get_key(&self) -> EuclidKey {
+        match self {
+            Self::PaymentMethod(_) => EuclidKey::PaymentMethod,
+            Self::CardBin(_) => EuclidKey::CardBin,
+            Self::Metadata(_) => EuclidKey::Metadata,
+            Self::PaymentMethodType(_) => EuclidKey::PaymentMethodType,
+            Self::MandateType(_) => EuclidKey::MandateType,
+            Self::PaymentType(_) => EuclidKey::PaymentType,
+            Self::MandateAcceptanceType(_) => EuclidKey::MandateAcceptanceType,
+            Self::CardNetwork(_) => EuclidKey::CardNetwork,
+            Self::AuthenticationType(_) => EuclidKey::AuthenticationType,
+            Self::CaptureMethod(_) => EuclidKey::CaptureMethod,
+            Self::PaymentAmount(_) => EuclidKey::PaymentAmount,
+            Self::PaymentCurrency(_) => EuclidKey::PaymentCurrency,
+            Self::BusinessCountry(_) => EuclidKey::BusinessCountry,
+            Self::BillingCountry(_) => EuclidKey::BillingCountry,
+            Self::BusinessLabel(_) => EuclidKey::BusinessLabel,
+            Self::SetupFutureUsage(_) => EuclidKey::SetupFutureUsage,
+        }
+    }
+}
+
+#[cfg(test)]
+mod global_type_tests {
+    use super::*;
+
+    #[test]
+    fn test_num_value_fits_greater_than() {
+        let val1 = NumValue {
+            number: 10,
+            refinement: Some(NumValueRefinement::GreaterThan),
+        };
+        let val2 = NumValue {
+            number: 30,
+            refinement: Some(NumValueRefinement::GreaterThan),
+        };
+
+        assert!(val1.fits(&val2))
+    }
+
+    #[test]
+    fn test_num_value_fits_less_than() {
+        let val1 = NumValue {
+            number: 30,
+            refinement: Some(NumValueRefinement::LessThan),
+        };
+        let val2 = NumValue {
+            number: 10,
+            refinement: Some(NumValueRefinement::LessThan),
+        };
+
+        assert!(val1.fits(&val2));
+    }
+}
diff --git a/crates/euclid/src/types/transformers.rs b/crates/euclid/src/types/transformers.rs
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/crates/euclid/src/types/transformers.rs
@@ -0,0 +1 @@
+
diff --git a/crates/euclid/src/utils.rs b/crates/euclid/src/utils.rs
new file mode 100644
index 000000000000..e8cb7901f0d7
--- /dev/null
+++ b/crates/euclid/src/utils.rs
@@ -0,0 +1,3 @@
+pub mod dense_map;
+
+pub use dense_map::{DenseMap, EntityId};
diff --git a/crates/euclid/src/utils/dense_map.rs b/crates/euclid/src/utils/dense_map.rs
new file mode 100644
index 000000000000..8bd4487c77b9
--- /dev/null
+++ b/crates/euclid/src/utils/dense_map.rs
@@ -0,0 +1,224 @@
+use std::{fmt, iter, marker::PhantomData, ops, slice, vec};
+
+pub trait EntityId {
+    fn get_id(&self) -> usize;
+    fn with_id(id: usize) -> Self;
+}
+
+pub struct DenseMap<K, V> {
+    data: Vec<V>,
+    _marker: PhantomData<K>,
+}
+
+impl<K, V> DenseMap<K, V> {
+    pub fn new() -> Self {
+        Self {
+            data: Vec::new(),
+            _marker: PhantomData,
+        }
+    }
+}
+
+impl<K, V> Default for DenseMap<K, V> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl<K, V> DenseMap<K, V>
+where
+    K: EntityId,
+{
+    pub fn push(&mut self, elem: V) -> K {
+        let curr_len = self.data.len();
+        self.data.push(elem);
+        K::with_id(curr_len)
+    }
+
+    #[inline]
+    pub fn get(&self, idx: K) -> Option<&V> {
+        self.data.get(idx.get_id())
+    }
+
+    #[inline]
+    pub fn get_mut(&mut self, idx: K) -> Option<&mut V> {
+        self.data.get_mut(idx.get_id())
+    }
+
+    #[inline]
+    pub fn contains_key(&self, key: K) -> bool {
+        key.get_id() < self.data.len()
+    }
+
+    #[inline]
+    pub fn keys(&self) -> Keys<K> {
+        Keys::new(0..self.data.len())
+    }
+
+    #[inline]
+    pub fn into_keys(self) -> Keys<K> {
+        Keys::new(0..self.data.len())
+    }
+
+    #[inline]
+    pub fn values(&self) -> slice::Iter<'_, V> {
+        self.data.iter()
+    }
+
+    #[inline]
+    pub fn values_mut(&mut self) -> slice::IterMut<'_, V> {
+        self.data.iter_mut()
+    }
+
+    #[inline]
+    pub fn into_values(self) -> vec::IntoIter<V> {
+        self.data.into_iter()
+    }
+
+    #[inline]
+    pub fn iter(&self) -> Iter<'_, K, V> {
+        Iter::new(self.data.iter())
+    }
+
+    #[inline]
+    pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
+        IterMut::new(self.data.iter_mut())
+    }
+}
+
+impl<K, V> fmt::Debug for DenseMap<K, V>
+where
+    K: EntityId + fmt::Debug,
+    V: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_map().entries(self.iter()).finish()
+    }
+}
+
+pub struct Keys<K> {
+    inner: ops::Range<usize>,
+    _marker: PhantomData<K>,
+}
+
+impl<K> Keys<K> {
+    fn new(range: ops::Range<usize>) -> Self {
+        Self {
+            inner: range,
+            _marker: PhantomData,
+        }
+    }
+}
+
+impl<K> Iterator for Keys<K>
+where
+    K: EntityId,
+{
+    type Item = K;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.inner.next().map(K::with_id)
+    }
+}
+
+pub struct Iter<'a, K, V> {
+    inner: iter::Enumerate<slice::Iter<'a, V>>,
+    _marker: PhantomData<K>,
+}
+
+impl<'a, K, V> Iter<'a, K, V> {
+    fn new(iter: slice::Iter<'a, V>) -> Self {
+        Self {
+            inner: iter.enumerate(),
+            _marker: PhantomData,
+        }
+    }
+}
+
+impl<'a, K, V> Iterator for Iter<'a, K, V>
+where
+    K: EntityId,
+{
+    type Item = (K, &'a V);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.inner.next().map(|(id, val)| (K::with_id(id), val))
+    }
+}
+
+pub struct IterMut<'a, K, V> {
+    inner: iter::Enumerate<slice::IterMut<'a, V>>,
+    _marker: PhantomData<K>,
+}
+
+impl<'a, K, V> IterMut<'a, K, V> {
+    fn new(iter: slice::IterMut<'a, V>) -> Self {
+        Self {
+            inner: iter.enumerate(),
+            _marker: PhantomData,
+        }
+    }
+}
+
+impl<'a, K, V> Iterator for IterMut<'a, K, V>
+where
+    K: EntityId,
+{
+    type Item = (K, &'a mut V);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.inner.next().map(|(id, val)| (K::with_id(id), val))
+    }
+}
+
+pub struct IntoIter<K, V> {
+    inner: iter::Enumerate<vec::IntoIter<V>>,
+    _marker: PhantomData<K>,
+}
+
+impl<K, V> IntoIter<K, V> {
+    fn new(iter: vec::IntoIter<V>) -> Self {
+        Self {
+            inner: iter.enumerate(),
+            _marker: PhantomData,
+        }
+    }
+}
+
+impl<K, V> Iterator for IntoIter<K, V>
+where
+    K: EntityId,
+{
+    type Item = (K, V);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.inner.next().map(|(id, val)| (K::with_id(id), val))
+    }
+}
+
+impl<K, V> IntoIterator for DenseMap<K, V>
+where
+    K: EntityId,
+{
+    type Item = (K, V);
+    type IntoIter = IntoIter<K, V>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        IntoIter::new(self.data.into_iter())
+    }
+}
+
+impl<K, V> FromIterator<V> for DenseMap<K, V>
+where
+    K: EntityId,
+{
+    fn from_iter<T>(iter: T) -> Self
+    where
+        T: IntoIterator<Item = V>,
+    {
+        Self {
+            data: Vec::from_iter(iter),
+            _marker: PhantomData,
+        }
+    }
+}
diff --git a/crates/euclid_macros/Cargo.toml b/crates/euclid_macros/Cargo.toml
new file mode 100644
index 000000000000..2524887a8a0f
--- /dev/null
+++ b/crates/euclid_macros/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "euclid_macros"
+description = "Macros for Euclid DSL"
+version = "0.1.0"
+edition.workspace = true
+rust-version.workspace = true
+
+[lib]
+proc-macro = true
+
+[dependencies]
+proc-macro2 = "1.0.51"
+quote = "1.0.23"
+rustc-hash = "1.1.0"
+strum = { version = "0.24", features = ["derive"] }
+syn = "1.0.109"
diff --git a/crates/euclid_macros/src/inner.rs b/crates/euclid_macros/src/inner.rs
new file mode 100644
index 000000000000..979527560dd6
--- /dev/null
+++ b/crates/euclid_macros/src/inner.rs
@@ -0,0 +1,5 @@
+mod enum_nums;
+mod knowledge;
+
+pub(crate) use enum_nums::enum_nums_inner;
+pub(crate) use knowledge::knowledge_inner;
diff --git a/crates/euclid_macros/src/inner/enum_nums.rs b/crates/euclid_macros/src/inner/enum_nums.rs
new file mode 100644
index 000000000000..61f6765fce0e
--- /dev/null
+++ b/crates/euclid_macros/src/inner/enum_nums.rs
@@ -0,0 +1,47 @@
+use proc_macro::TokenStream;
+use proc_macro2::{Span, TokenStream as TokenStream2};
+use quote::quote;
+
+fn error() -> TokenStream2 {
+    syn::Error::new(
+        Span::call_site(),
+        "'EnumNums' can only be derived on enums with unit variants".to_string(),
+    )
+    .to_compile_error()
+}
+
+pub(crate) fn enum_nums_inner(ts: TokenStream) -> TokenStream {
+    let derive_input = syn::parse_macro_input!(ts as syn::DeriveInput);
+
+    let enum_obj = match derive_input.data {
+        syn::Data::Enum(e) => e,
+        _ => return error().into(),
+    };
+
+    let enum_name = derive_input.ident;
+
+    let mut match_arms = Vec::<TokenStream2>::with_capacity(enum_obj.variants.len());
+
+    for (i, variant) in enum_obj.variants.iter().enumerate() {
+        match variant.fields {
+            syn::Fields::Unit => {}
+            _ => return error().into(),
+        }
+
+        let var_ident = &variant.ident;
+
+        match_arms.push(quote! { Self::#var_ident => #i });
+    }
+
+    let impl_block = quote! {
+        impl #enum_name {
+            pub fn to_num(&self) -> usize {
+                match self {
+                    #(#match_arms),*
+                }
+            }
+        }
+    };
+
+    impl_block.into()
+}
diff --git a/crates/euclid_macros/src/inner/knowledge.rs b/crates/euclid_macros/src/inner/knowledge.rs
new file mode 100644
index 000000000000..73b94919c903
--- /dev/null
+++ b/crates/euclid_macros/src/inner/knowledge.rs
@@ -0,0 +1,680 @@
+use std::{hash::Hash, rc::Rc};
+
+use proc_macro2::{Span, TokenStream};
+use quote::{format_ident, quote};
+use rustc_hash::{FxHashMap, FxHashSet};
+use syn::{parse::Parse, Token};
+
+mod strength {
+    syn::custom_punctuation!(Normal, ->);
+    syn::custom_punctuation!(Strong, ->>);
+}
+
+mod kw {
+    syn::custom_keyword!(any);
+    syn::custom_keyword!(not);
+}
+
+#[derive(Clone, PartialEq, Eq, Hash)]
+enum Comparison {
+    LessThan,
+    Equal,
+    GreaterThan,
+    GreaterThanEqual,
+    LessThanEqual,
+}
+
+impl ToString for Comparison {
+    fn to_string(&self) -> String {
+        match self {
+            Self::LessThan => "< ".to_string(),
+            Self::Equal => String::new(),
+            Self::GreaterThanEqual => ">= ".to_string(),
+            Self::LessThanEqual => "<= ".to_string(),
+            Self::GreaterThan => "> ".to_string(),
+        }
+    }
+}
+
+impl Parse for Comparison {
+    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
+        if input.peek(Token![>]) {
+            input.parse::<Token![>]>()?;
+            Ok(Self::GreaterThan)
+        } else if input.peek(Token![<]) {
+            input.parse::<Token![<]>()?;
+            Ok(Self::LessThan)
+        } else if input.peek(Token!(<=)) {
+            input.parse::<Token![<=]>()?;
+            Ok(Self::LessThanEqual)
+        } else if input.peek(Token!(>=)) {
+            input.parse::<Token![>=]>()?;
+            Ok(Self::GreaterThanEqual)
+        } else {
+            Ok(Self::Equal)
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Hash)]
+enum ValueType {
+    Any,
+    EnumVariant(String),
+    Number { number: i64, comparison: Comparison },
+}
+
+impl ValueType {
+    fn to_string(&self, key: &str) -> String {
+        match self {
+            Self::Any => format!("{key}(any)"),
+            Self::EnumVariant(s) => format!("{key}({s})"),
+            Self::Number { number, comparison } => {
+                format!("{}({}{})", key, comparison.to_string(), number)
+            }
+        }
+    }
+}
+
+impl Parse for ValueType {
+    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
+        let lookahead = input.lookahead1();
+        if lookahead.peek(syn::Ident) {
+            let ident: syn::Ident = input.parse()?;
+            Ok(Self::EnumVariant(ident.to_string()))
+        } else if lookahead.peek(Token![>])
+            || lookahead.peek(Token![<])
+            || lookahead.peek(syn::LitInt)
+        {
+            let comparison: Comparison = input.parse()?;
+            let number: syn::LitInt = input.parse()?;
+            let num_val = number.base10_parse::<i64>()?;
+            Ok(Self::Number {
+                number: num_val,
+                comparison,
+            })
+        } else {
+            Err(lookahead.error())
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Hash)]
+struct Atom {
+    key: String,
+    value: ValueType,
+}
+
+impl ToString for Atom {
+    fn to_string(&self) -> String {
+        self.value.to_string(&self.key)
+    }
+}
+
+impl Parse for Atom {
+    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
+        let maybe_any: syn::Ident = input.parse()?;
+        if maybe_any == "any" {
+            let actual_key: syn::Ident = input.parse()?;
+            Ok(Self {
+                key: actual_key.to_string(),
+                value: ValueType::Any,
+            })
+        } else {
+            let content;
+            syn::parenthesized!(content in input);
+            let value: ValueType = content.parse()?;
+            Ok(Self {
+                key: maybe_any.to_string(),
+                value,
+            })
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Hash, strum::Display)]
+enum Strength {
+    Normal,
+    Strong,
+}
+
+impl Parse for Strength {
+    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
+        let lookahead = input.lookahead1();
+        if lookahead.peek(strength::Strong) {
+            input.parse::<strength::Strong>()?;
+            Ok(Self::Strong)
+        } else if lookahead.peek(strength::Normal) {
+            input.parse::<strength::Normal>()?;
+            Ok(Self::Normal)
+        } else {
+            Err(lookahead.error())
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Hash, strum::Display)]
+enum Relation {
+    Positive,
+    Negative,
+}
+
+enum AtomType {
+    Value {
+        relation: Relation,
+        atom: Rc<Atom>,
+    },
+
+    InAggregator {
+        key: String,
+        values: Vec<String>,
+        relation: Relation,
+    },
+}
+
+fn parse_atom_type_inner(
+    input: syn::parse::ParseStream<'_>,
+    key: syn::Ident,
+    relation: Relation,
+) -> syn::Result<AtomType> {
+    let result = if input.peek(Token![in]) {
+        input.parse::<Token![in]>()?;
+
+        let bracketed;
+        syn::bracketed!(bracketed in input);
+
+        let mut values = Vec::<String>::new();
+        let first: syn::Ident = bracketed.parse()?;
+        values.push(first.to_string());
+        while !bracketed.is_empty() {
+            bracketed.parse::<Token![,]>()?;
+            let next: syn::Ident = bracketed.parse()?;
+            values.push(next.to_string());
+        }
+
+        AtomType::InAggregator {
+            key: key.to_string(),
+            values,
+            relation,
+        }
+    } else if input.peek(kw::any) {
+        input.parse::<kw::any>()?;
+        AtomType::Value {
+            relation,
+            atom: Rc::new(Atom {
+                key: key.to_string(),
+                value: ValueType::Any,
+            }),
+        }
+    } else {
+        let value: ValueType = input.parse()?;
+        AtomType::Value {
+            relation,
+            atom: Rc::new(Atom {
+                key: key.to_string(),
+                value,
+            }),
+        }
+    };
+
+    Ok(result)
+}
+
+impl Parse for AtomType {
+    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
+        let key: syn::Ident = input.parse()?;
+        let content;
+        syn::parenthesized!(content in input);
+
+        let relation = if content.peek(kw::not) {
+            content.parse::<kw::not>()?;
+            Relation::Negative
+        } else {
+            Relation::Positive
+        };
+
+        let result = parse_atom_type_inner(&content, key, relation)?;
+
+        if !content.is_empty() {
+            Err(content.error("Unexpected input received after atom value"))
+        } else {
+            Ok(result)
+        }
+    }
+}
+
+fn parse_rhs_atom(input: syn::parse::ParseStream<'_>) -> syn::Result<Atom> {
+    let key: syn::Ident = input.parse()?;
+    let content;
+    syn::parenthesized!(content in input);
+
+    let lookahead = content.lookahead1();
+
+    let value_type = if lookahead.peek(kw::any) {
+        content.parse::<kw::any>()?;
+        ValueType::Any
+    } else if lookahead.peek(syn::Ident) {
+        let variant = content.parse::<syn::Ident>()?;
+        ValueType::EnumVariant(variant.to_string())
+    } else {
+        return Err(lookahead.error());
+    };
+
+    if !content.is_empty() {
+        Err(content.error("Unexpected input received after atom value"))
+    } else {
+        Ok(Atom {
+            key: key.to_string(),
+            value: value_type,
+        })
+    }
+}
+
+struct Rule {
+    lhs: Vec<AtomType>,
+    strength: Strength,
+    rhs: Rc<Atom>,
+}
+
+impl Parse for Rule {
+    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
+        let first_atom: AtomType = input.parse()?;
+        let mut lhs: Vec<AtomType> = vec![first_atom];
+
+        while input.peek(Token![&]) {
+            input.parse::<Token![&]>()?;
+            let and_atom: AtomType = input.parse()?;
+            lhs.push(and_atom);
+        }
+
+        let strength: Strength = input.parse()?;
+
+        let rhs: Rc<Atom> = Rc::new(parse_rhs_atom(input)?);
+
+        input.parse::<Token![;]>()?;
+
+        Ok(Self { lhs, strength, rhs })
+    }
+}
+
+#[derive(Clone)]
+enum Scope {
+    Crate,
+    Extern,
+}
+
+impl Parse for Scope {
+    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
+        let lookahead = input.lookahead1();
+        if lookahead.peek(Token![crate]) {
+            input.parse::<Token![crate]>()?;
+            Ok(Self::Crate)
+        } else if lookahead.peek(Token![extern]) {
+            input.parse::<Token![extern]>()?;
+            Ok(Self::Extern)
+        } else {
+            Err(lookahead.error())
+        }
+    }
+}
+
+impl ToString for Scope {
+    fn to_string(&self) -> String {
+        match self {
+            Self::Crate => "crate".to_string(),
+            Self::Extern => "euclid".to_string(),
+        }
+    }
+}
+
+#[derive(Clone)]
+struct Program {
+    rules: Vec<Rc<Rule>>,
+    scope: Scope,
+}
+
+impl Parse for Program {
+    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
+        let scope: Scope = input.parse()?;
+        let mut rules: Vec<Rc<Rule>> = Vec::new();
+
+        while !input.is_empty() {
+            rules.push(Rc::new(input.parse::<Rule>()?));
+        }
+
+        Ok(Self { rules, scope })
+    }
+}
+
+struct GenContext {
+    next_idx: usize,
+    next_node_idx: usize,
+    idx2atom: FxHashMap<usize, Rc<Atom>>,
+    atom2idx: FxHashMap<Rc<Atom>, usize>,
+    edges: FxHashMap<usize, FxHashSet<usize>>,
+    compiled_atoms: FxHashMap<Rc<Atom>, proc_macro2::Ident>,
+}
+
+impl GenContext {
+    fn new() -> Self {
+        Self {
+            next_idx: 1,
+            next_node_idx: 1,
+            idx2atom: FxHashMap::default(),
+            atom2idx: FxHashMap::default(),
+            edges: FxHashMap::default(),
+            compiled_atoms: FxHashMap::default(),
+        }
+    }
+
+    fn register_node(&mut self, atom: Rc<Atom>) -> usize {
+        if let Some(idx) = self.atom2idx.get(&atom) {
+            *idx
+        } else {
+            let this_idx = self.next_idx;
+            self.next_idx += 1;
+
+            self.idx2atom.insert(this_idx, Rc::clone(&atom));
+            self.atom2idx.insert(atom, this_idx);
+
+            this_idx
+        }
+    }
+
+    fn register_edge(&mut self, from: usize, to: usize) -> Result<(), String> {
+        let node_children = self.edges.entry(from).or_default();
+        if node_children.contains(&to) {
+            Err("Duplicate edge detected".to_string())
+        } else {
+            node_children.insert(to);
+            self.edges.entry(to).or_default();
+            Ok(())
+        }
+    }
+
+    fn register_rule(&mut self, rule: &Rule) -> Result<(), String> {
+        let to_idx = self.register_node(Rc::clone(&rule.rhs));
+
+        for atom_type in &rule.lhs {
+            if let AtomType::Value { atom, .. } = atom_type {
+                let from_idx = self.register_node(Rc::clone(atom));
+                self.register_edge(from_idx, to_idx)?;
+            }
+        }
+
+        Ok(())
+    }
+
+    fn cycle_dfs(
+        &self,
+        node_id: usize,
+        explored: &mut FxHashSet<usize>,
+        visited: &mut FxHashSet<usize>,
+        order: &mut Vec<usize>,
+    ) -> Result<Option<Vec<usize>>, String> {
+        if explored.contains(&node_id) {
+            let position = order
+                .iter()
+                .position(|v| *v == node_id)
+                .ok_or_else(|| "Error deciding cycle order".to_string())?;
+
+            let cycle_order = order[position..].to_vec();
+            Ok(Some(cycle_order))
+        } else if visited.contains(&node_id) {
+            Ok(None)
+        } else {
+            visited.insert(node_id);
+            explored.insert(node_id);
+            order.push(node_id);
+            let dests = self
+                .edges
+                .get(&node_id)
+                .ok_or_else(|| "Error getting edges of node".to_string())?;
+
+            for dest in dests.iter().copied() {
+                if let Some(cycle) = self.cycle_dfs(dest, explored, visited, order)? {
+                    return Ok(Some(cycle));
+                }
+            }
+
+            order.pop();
+
+            Ok(None)
+        }
+    }
+
+    fn detect_graph_cycles(&self) -> Result<(), String> {
+        let start_nodes = self.edges.keys().copied().collect::<Vec<usize>>();
+
+        let mut total_visited = FxHashSet::<usize>::default();
+
+        for node_id in start_nodes.iter().copied() {
+            let mut explored = FxHashSet::<usize>::default();
+            let mut order = Vec::<usize>::new();
+
+            match self.cycle_dfs(node_id, &mut explored, &mut total_visited, &mut order)? {
+                None => {}
+                Some(order) => {
+                    let mut display_strings = Vec::<String>::with_capacity(order.len() + 1);
+
+                    for cycle_node_id in order {
+                        let node = self.idx2atom.get(&cycle_node_id).ok_or_else(|| {
+                            "Failed to find node during cycle display creation".to_string()
+                        })?;
+
+                        display_strings.push(node.to_string());
+                    }
+
+                    let first = display_strings
+                        .first()
+                        .cloned()
+                        .ok_or("Unable to fill cycle display array")?;
+
+                    display_strings.push(first);
+
+                    return Err(format!("Found cycle: {}", display_strings.join(" -> ")));
+                }
+            }
+        }
+
+        Ok(())
+    }
+
+    fn next_node_ident(&mut self) -> (proc_macro2::Ident, usize) {
+        let this_idx = self.next_node_idx;
+        self.next_node_idx += 1;
+        (format_ident!("_node_{this_idx}"), this_idx)
+    }
+
+    fn compile_atom(
+        &mut self,
+        atom: &Rc<Atom>,
+        tokens: &mut TokenStream,
+    ) -> Result<proc_macro2::Ident, String> {
+        let maybe_ident = self.compiled_atoms.get(atom);
+
+        if let Some(ident) = maybe_ident {
+            Ok(ident.clone())
+        } else {
+            let (identifier, _) = self.next_node_ident();
+            let key = format_ident!("{}", &atom.key);
+            let the_value = match &atom.value {
+                ValueType::Any => quote! {
+                    NodeValue::Key(DirKey::new(DirKeyKind::#key,None))
+                },
+                ValueType::EnumVariant(variant) => {
+                    let variant = format_ident!("{}", variant);
+                    quote! {
+                        NodeValue::Value(DirValue::#key(#key::#variant))
+                    }
+                }
+                ValueType::Number { number, comparison } => {
+                    let comp_type = match comparison {
+                        Comparison::Equal => quote! {
+                            None
+                        },
+                        Comparison::LessThan => quote! {
+                            Some(NumValueRefinement::LessThan)
+                        },
+                        Comparison::GreaterThan => quote! {
+                            Some(NumValueRefinement::GreaterThan)
+                        },
+                        Comparison::GreaterThanEqual => quote! {
+                            Some(NumValueRefinement::GreaterThanEqual)
+                        },
+                        Comparison::LessThanEqual => quote! {
+                            Some(NumValueRefinement::LessThanEqual)
+                        },
+                    };
+
+                    quote! {
+                        NodeValue::Value(DirValue::#key(NumValue {
+                            number: #number,
+                            refinement: #comp_type,
+                        }))
+                    }
+                }
+            };
+
+            let compiled = quote! {
+                let #identifier = graph.make_value_node(#the_value, None, Vec::new(), None::<()>).expect("NodeId derivation failed");
+            };
+
+            tokens.extend(compiled);
+            self.compiled_atoms
+                .insert(Rc::clone(atom), identifier.clone());
+
+            Ok(identifier)
+        }
+    }
+
+    fn compile_atom_type(
+        &mut self,
+        atom_type: &AtomType,
+        tokens: &mut TokenStream,
+    ) -> Result<(proc_macro2::Ident, Relation), String> {
+        match atom_type {
+            AtomType::Value { relation, atom } => {
+                let node_ident = self.compile_atom(atom, tokens)?;
+
+                Ok((node_ident, relation.clone()))
+            }
+
+            AtomType::InAggregator {
+                key,
+                values,
+                relation,
+            } => {
+                let key_ident = format_ident!("{key}");
+                let mut values_tokens: Vec<TokenStream> = Vec::new();
+
+                for value in values {
+                    let value_ident = format_ident!("{value}");
+                    values_tokens.push(quote! { DirValue::#key_ident(#key_ident::#value_ident) });
+                }
+
+                let (node_ident, _) = self.next_node_ident();
+                let node_code = quote! {
+                    let #node_ident = graph.make_in_aggregator(
+                        Vec::from_iter([#(#values_tokens),*]),
+                        None,
+                        None::<()>,
+                        Vec::new(),
+                    ).expect("Failed to make In aggregator");
+                };
+
+                tokens.extend(node_code);
+
+                Ok((node_ident, relation.clone()))
+            }
+        }
+    }
+
+    fn compile_rule(&mut self, rule: &Rule, tokens: &mut TokenStream) -> Result<(), String> {
+        let rhs_ident = self.compile_atom(&rule.rhs, tokens)?;
+        let mut node_details: Vec<(proc_macro2::Ident, Relation)> =
+            Vec::with_capacity(rule.lhs.len());
+        for lhs_atom_type in &rule.lhs {
+            let details = self.compile_atom_type(lhs_atom_type, tokens)?;
+            node_details.push(details);
+        }
+
+        if node_details.len() <= 1 {
+            let strength = format_ident!("{}", rule.strength.to_string());
+            for (from_node, relation) in &node_details {
+                let relation = format_ident!("{}", relation.to_string());
+                tokens.extend(quote! {
+                    graph.make_edge(#from_node, #rhs_ident, Strength::#strength, Relation::#relation)
+                        .expect("Failed to make edge");
+                });
+            }
+        } else {
+            let mut all_agg_nodes: Vec<TokenStream> = Vec::with_capacity(node_details.len());
+            for (from_node, relation) in &node_details {
+                let relation = format_ident!("{}", relation.to_string());
+                all_agg_nodes.push(quote! { (#from_node, Relation::#relation, Strength::Strong) });
+            }
+
+            let strength = format_ident!("{}", rule.strength.to_string());
+            let (agg_node_ident, _) = self.next_node_ident();
+            tokens.extend(quote! {
+                let #agg_node_ident = graph.make_all_aggregator(&[#(#all_agg_nodes),*], None, None::<()>, Vec::new())
+                    .expect("Failed to make all aggregator node");
+
+                graph.make_edge(#agg_node_ident, #rhs_ident, Strength::#strength, Relation::Positive)
+                    .expect("Failed to create all aggregator edge");
+
+            });
+        }
+
+        Ok(())
+    }
+
+    fn compile(&mut self, program: Program) -> Result<TokenStream, String> {
+        let mut tokens = TokenStream::new();
+        for rule in &program.rules {
+            self.compile_rule(rule, &mut tokens)?;
+        }
+
+        let scope = match &program.scope {
+            Scope::Crate => quote! { crate },
+            Scope::Extern => quote! { euclid },
+        };
+
+        let compiled = quote! {{
+            use #scope::{
+                dssa::graph::*,
+                types::*,
+                frontend::dir::{*, enums::*},
+            };
+
+            use rustc_hash::{FxHashMap, FxHashSet};
+
+            let mut graph = KnowledgeGraphBuilder::new();
+
+            #tokens
+
+            graph.build()
+        }};
+
+        Ok(compiled)
+    }
+}
+
+pub(crate) fn knowledge_inner(ts: TokenStream) -> syn::Result<TokenStream> {
+    let program = syn::parse::<Program>(ts.into())?;
+    let mut gen_context = GenContext::new();
+
+    for rule in &program.rules {
+        gen_context
+            .register_rule(rule)
+            .map_err(|msg| syn::Error::new(Span::call_site(), msg))?;
+    }
+
+    gen_context
+        .detect_graph_cycles()
+        .map_err(|msg| syn::Error::new(Span::call_site(), msg))?;
+
+    gen_context
+        .compile(program)
+        .map_err(|msg| syn::Error::new(Span::call_site(), msg))
+}
diff --git a/crates/euclid_macros/src/lib.rs b/crates/euclid_macros/src/lib.rs
new file mode 100644
index 000000000000..97b42aaa64c1
--- /dev/null
+++ b/crates/euclid_macros/src/lib.rs
@@ -0,0 +1,16 @@
+mod inner;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(EnumNums)]
+pub fn enum_nums(ts: TokenStream) -> TokenStream {
+    inner::enum_nums_inner(ts)
+}
+
+#[proc_macro]
+pub fn knowledge(ts: TokenStream) -> TokenStream {
+    match inner::knowledge_inner(ts.into()) {
+        Ok(ts) => ts.into(),
+        Err(e) => e.into_compile_error().into(),
+    }
+}
diff --git a/crates/euclid_wasm/Cargo.toml b/crates/euclid_wasm/Cargo.toml
new file mode 100644
index 000000000000..4fc8cd970f40
--- /dev/null
+++ b/crates/euclid_wasm/Cargo.toml
@@ -0,0 +1,30 @@
+[package]
+name = "euclid_wasm"
+description = "WASM bindings for Euclid DSL"
+version = "0.1.0"
+edition.workspace = true
+rust-version.workspace = true
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[lib]
+crate-type = ["cdylib"]
+
+[features]
+default = ["connector_choice_bcompat"]
+connector_choice_bcompat = ["api_models/connector_choice_bcompat"]
+connector_choice_mca_id = ["api_models/connector_choice_mca_id", "euclid/connector_choice_mca_id", "kgraph_utils/connector_choice_mca_id"]
+dummy_connector = ["kgraph_utils/dummy_connector"]
+
+[dependencies]
+api_models = { version = "0.1.0", path = "../api_models", package = "api_models" }
+euclid = { path = "../euclid", features = [] }
+kgraph_utils = { version = "0.1.0", path = "../kgraph_utils" }
+
+# Third party crates
+getrandom = { version = "0.2.10", features = ["js"] }
+once_cell = "1.18.0"
+ron-parser = "0.1.4"
+serde = { version = "1.0", features = [] }
+serde-wasm-bindgen = "0.5"
+strum = { version = "0.25", features = ["derive"] }
+wasm-bindgen = { version = "0.2.86" }
diff --git a/crates/euclid_wasm/src/lib.rs b/crates/euclid_wasm/src/lib.rs
new file mode 100644
index 000000000000..e85a002544ff
--- /dev/null
+++ b/crates/euclid_wasm/src/lib.rs
@@ -0,0 +1,227 @@
+#![allow(non_upper_case_globals)]
+mod types;
+mod utils;
+use std::{
+    collections::{HashMap, HashSet},
+    str::FromStr,
+};
+
+use api_models::{admin as admin_api, routing::ConnectorSelection};
+use euclid::{
+    backend::{inputs, interpreter::InterpreterBackend, EuclidBackend},
+    dssa::{
+        self, analyzer,
+        graph::{self, Memoization},
+        state_machine, truth,
+    },
+    enums,
+    frontend::{
+        ast,
+        dir::{self, enums as dir_enums},
+    },
+};
+use once_cell::sync::OnceCell;
+use strum::{EnumMessage, EnumProperty, VariantNames};
+use wasm_bindgen::prelude::*;
+
+use crate::utils::JsResultExt;
+type JsResult = Result<JsValue, JsValue>;
+
+struct SeedData<'a> {
+    kgraph: graph::KnowledgeGraph<'a>,
+    connectors: Vec<ast::ConnectorChoice>,
+}
+
+static SEED_DATA: OnceCell<SeedData<'_>> = OnceCell::new();
+
+/// This function can be used by the frontend to provide the WASM with information about
+/// all the merchant's connector accounts. The input argument is a vector of all the merchant's
+/// connector accounts from the API.
+#[wasm_bindgen(js_name = seedKnowledgeGraph)]
+pub fn seed_knowledge_graph(mcas: JsValue) -> JsResult {
+    let mcas: Vec<admin_api::MerchantConnectorResponse> = serde_wasm_bindgen::from_value(mcas)?;
+    let connectors: Vec<ast::ConnectorChoice> = mcas
+        .iter()
+        .map(|mca| {
+            Ok::<_, strum::ParseError>(ast::ConnectorChoice {
+                connector: dir_enums::Connector::from_str(&mca.connector_name)?,
+                #[cfg(not(feature = "connector_choice_mca_id"))]
+                sub_label: mca.business_sub_label.clone(),
+            })
+        })
+        .collect::<Result<_, _>>()
+        .map_err(|_| "invalid connector name received")
+        .err_to_js()?;
+
+    let mca_graph = kgraph_utils::mca::make_mca_graph(mcas).err_to_js()?;
+    let analysis_graph =
+        graph::KnowledgeGraph::combine(&mca_graph, &truth::ANALYSIS_GRAPH).err_to_js()?;
+
+    SEED_DATA
+        .set(SeedData {
+            kgraph: analysis_graph,
+            connectors,
+        })
+        .map_err(|_| "Knowledge Graph has been already seeded".to_string())
+        .err_to_js()?;
+
+    Ok(JsValue::NULL)
+}
+
+/// This function allows the frontend to get all the merchant's configured
+/// connectors that are valid for a rule based on the conditions specified in
+/// the rule
+#[wasm_bindgen(js_name = getValidConnectorsForRule)]
+pub fn get_valid_connectors_for_rule(rule: JsValue) -> JsResult {
+    let seed_data = SEED_DATA.get().ok_or("Data not seeded").err_to_js()?;
+
+    let rule: ast::Rule<ConnectorSelection> = serde_wasm_bindgen::from_value(rule)?;
+    let dir_rule = ast::lowering::lower_rule(rule).err_to_js()?;
+    let mut valid_connectors: Vec<(ast::ConnectorChoice, dir::DirValue)> = seed_data
+        .connectors
+        .iter()
+        .cloned()
+        .map(|choice| (choice.clone(), dir::DirValue::Connector(Box::new(choice))))
+        .collect();
+    let mut invalid_connectors: HashSet<ast::ConnectorChoice> = HashSet::new();
+
+    let mut ctx_manager = state_machine::RuleContextManager::new(&dir_rule, &[]);
+
+    let dummy_meta = HashMap::new();
+
+    // For every conjunctive context in the Rule, verify validity of all still-valid connectors
+    // using the knowledge graph
+    while let Some(ctx) = ctx_manager.advance_mut().err_to_js()? {
+        // Standalone conjunctive context analysis to ensure the context itself is valid before
+        // checking it against merchant's connectors
+        seed_data
+            .kgraph
+            .perform_context_analysis(ctx, &mut Memoization::new())
+            .err_to_js()?;
+
+        // Update conjunctive context and run analysis on all of merchant's connectors.
+        for (conn, choice) in &valid_connectors {
+            if invalid_connectors.contains(conn) {
+                continue;
+            }
+
+            let ctx_val = dssa::types::ContextValue::assertion(choice, &dummy_meta);
+            ctx.push(ctx_val);
+            let analysis_result = seed_data
+                .kgraph
+                .perform_context_analysis(ctx, &mut Memoization::new());
+            if analysis_result.is_err() {
+                invalid_connectors.insert(conn.clone());
+            }
+            ctx.pop();
+        }
+    }
+
+    valid_connectors.retain(|(k, _)| !invalid_connectors.contains(k));
+
+    let valid_connectors: Vec<ast::ConnectorChoice> =
+        valid_connectors.into_iter().map(|c| c.0).collect();
+
+    Ok(serde_wasm_bindgen::to_value(&valid_connectors)?)
+}
+
+#[wasm_bindgen(js_name = analyzeProgram)]
+pub fn analyze_program(js_program: JsValue) -> JsResult {
+    let program: ast::Program<ConnectorSelection> = serde_wasm_bindgen::from_value(js_program)?;
+    analyzer::analyze(program, SEED_DATA.get().map(|sd| &sd.kgraph)).err_to_js()?;
+    Ok(JsValue::NULL)
+}
+
+#[wasm_bindgen(js_name = runProgram)]
+pub fn run_program(program: JsValue, input: JsValue) -> JsResult {
+    let program: ast::Program<ConnectorSelection> = serde_wasm_bindgen::from_value(program)?;
+    let input: inputs::BackendInput = serde_wasm_bindgen::from_value(input)?;
+
+    let backend = InterpreterBackend::with_program(program).err_to_js()?;
+
+    let res: euclid::backend::BackendOutput<ConnectorSelection> =
+        backend.execute(input).err_to_js()?;
+
+    Ok(serde_wasm_bindgen::to_value(&res)?)
+}
+
+#[wasm_bindgen(js_name = getAllConnectors)]
+pub fn get_all_connectors() -> JsResult {
+    Ok(serde_wasm_bindgen::to_value(enums::Connector::VARIANTS)?)
+}
+
+#[wasm_bindgen(js_name = getAllKeys)]
+pub fn get_all_keys() -> JsResult {
+    let keys: Vec<&'static str> = dir::DirKeyKind::VARIANTS
+        .iter()
+        .copied()
+        .filter(|s| s != &"Connector")
+        .collect();
+    Ok(serde_wasm_bindgen::to_value(&keys)?)
+}
+
+#[wasm_bindgen(js_name = getKeyType)]
+pub fn get_key_type(key: &str) -> Result<String, String> {
+    let key = dir::DirKeyKind::from_str(key).map_err(|_| "Invalid key received".to_string())?;
+    let key_str = key.get_type().to_string();
+    Ok(key_str)
+}
+
+#[wasm_bindgen(js_name=parseToString)]
+pub fn parser(val: String) -> String {
+    ron_parser::my_parse(val)
+}
+
+#[wasm_bindgen(js_name = getVariantValues)]
+pub fn get_variant_values(key: &str) -> Result<JsValue, JsValue> {
+    let key = dir::DirKeyKind::from_str(key).map_err(|_| "Invalid key received".to_string())?;
+
+    let variants: &[&str] = match key {
+        dir::DirKeyKind::PaymentMethod => dir_enums::PaymentMethod::VARIANTS,
+        dir::DirKeyKind::CardType => dir_enums::CardType::VARIANTS,
+        dir::DirKeyKind::CardNetwork => dir_enums::CardNetwork::VARIANTS,
+        dir::DirKeyKind::PayLaterType => dir_enums::PayLaterType::VARIANTS,
+        dir::DirKeyKind::WalletType => dir_enums::WalletType::VARIANTS,
+        dir::DirKeyKind::BankRedirectType => dir_enums::BankRedirectType::VARIANTS,
+        dir::DirKeyKind::CryptoType => dir_enums::CryptoType::VARIANTS,
+        dir::DirKeyKind::RewardType => dir_enums::RewardType::VARIANTS,
+        dir::DirKeyKind::AuthenticationType => dir_enums::AuthenticationType::VARIANTS,
+        dir::DirKeyKind::CaptureMethod => dir_enums::CaptureMethod::VARIANTS,
+        dir::DirKeyKind::PaymentCurrency => dir_enums::PaymentCurrency::VARIANTS,
+        dir::DirKeyKind::BusinessCountry => dir_enums::Country::VARIANTS,
+        dir::DirKeyKind::BillingCountry => dir_enums::Country::VARIANTS,
+        dir::DirKeyKind::BankTransferType => dir_enums::BankTransferType::VARIANTS,
+        dir::DirKeyKind::UpiType => dir_enums::UpiType::VARIANTS,
+        dir::DirKeyKind::SetupFutureUsage => dir_enums::SetupFutureUsage::VARIANTS,
+        dir::DirKeyKind::PaymentType => dir_enums::PaymentType::VARIANTS,
+        dir::DirKeyKind::MandateType => dir_enums::MandateType::VARIANTS,
+        dir::DirKeyKind::MandateAcceptanceType => dir_enums::MandateAcceptanceType::VARIANTS,
+        dir::DirKeyKind::CardRedirectType => dir_enums::CardRedirectType::VARIANTS,
+        dir::DirKeyKind::GiftCardType => dir_enums::GiftCardType::VARIANTS,
+        dir::DirKeyKind::VoucherType => dir_enums::VoucherType::VARIANTS,
+        dir::DirKeyKind::PaymentAmount
+        | dir::DirKeyKind::Connector
+        | dir::DirKeyKind::CardBin
+        | dir::DirKeyKind::BusinessLabel
+        | dir::DirKeyKind::MetaData => Err("Key does not have variants".to_string())?,
+        dir::DirKeyKind::BankDebitType => dir_enums::BankDebitType::VARIANTS,
+    };
+
+    Ok(serde_wasm_bindgen::to_value(variants)?)
+}
+
+#[wasm_bindgen(js_name = addTwo)]
+pub fn add_two(n1: i64, n2: i64) -> i64 {
+    n1 + n2
+}
+
+#[wasm_bindgen(js_name = getDescriptionCategory)]
+pub fn get_description_category(key: &str) -> JsResult {
+    let key = dir::DirKeyKind::from_str(key).map_err(|_| "Invalid key received".to_string())?;
+
+    let result = types::Details {
+        description: key.get_detailed_message(),
+        category: key.get_str("Category"),
+    };
+    Ok(serde_wasm_bindgen::to_value(&result)?)
+}
diff --git a/crates/euclid_wasm/src/types.rs b/crates/euclid_wasm/src/types.rs
new file mode 100644
index 000000000000..ea40449971bc
--- /dev/null
+++ b/crates/euclid_wasm/src/types.rs
@@ -0,0 +1,7 @@
+use serde::Serialize;
+
+#[derive(Serialize, Clone)]
+pub struct Details<'a> {
+    pub description: Option<&'a str>,
+    pub category: Option<&'a str>,
+}
diff --git a/crates/euclid_wasm/src/utils.rs b/crates/euclid_wasm/src/utils.rs
new file mode 100644
index 000000000000..c531dabd7e2a
--- /dev/null
+++ b/crates/euclid_wasm/src/utils.rs
@@ -0,0 +1,17 @@
+use wasm_bindgen::prelude::*;
+
+pub trait JsResultExt<T> {
+    fn err_to_js(self) -> Result<T, JsValue>;
+}
+
+impl<T, E> JsResultExt<T> for Result<T, E>
+where
+    E: serde::Serialize,
+{
+    fn err_to_js(self) -> Result<T, JsValue> {
+        match self {
+            Ok(t) => Ok(t),
+            Err(e) => Err(serde_wasm_bindgen::to_value(&e)?),
+        }
+    }
+}
diff --git a/crates/kgraph_utils/Cargo.toml b/crates/kgraph_utils/Cargo.toml
new file mode 100644
index 000000000000..cd0adf0bc8af
--- /dev/null
+++ b/crates/kgraph_utils/Cargo.toml
@@ -0,0 +1,27 @@
+[package]
+name = "kgraph_utils"
+description = "Utilities for constructing and working with Knowledge Graphs"
+version = "0.1.0"
+edition.workspace = true
+rust-version.workspace = true
+
+[features]
+dummy_connector = ["api_models/dummy_connector", "euclid/dummy_connector"]
+connector_choice_mca_id = ["api_models/connector_choice_mca_id", "euclid/connector_choice_mca_id"]
+
+[dependencies]
+api_models = { version = "0.1.0", path = "../api_models", package = "api_models" }
+euclid = { version = "0.1.0", path = "../euclid" }
+masking = { version = "0.1.0", path = "../masking/" }
+
+# Third party crates
+serde = "1.0.163"
+serde_json = "1.0.96"
+thiserror = "1.0.43"
+
+[dev-dependencies]
+criterion = "0.5"
+
+[[bench]]
+name = "evaluation"
+harness = false
diff --git a/crates/kgraph_utils/benches/evaluation.rs b/crates/kgraph_utils/benches/evaluation.rs
new file mode 100644
index 000000000000..ecea12203f8a
--- /dev/null
+++ b/crates/kgraph_utils/benches/evaluation.rs
@@ -0,0 +1,113 @@
+#![allow(unused, clippy::expect_used)]
+
+use std::str::FromStr;
+
+use api_models::{
+    admin as admin_api, enums as api_enums, payment_methods::RequestPaymentMethodTypes,
+};
+use criterion::{black_box, criterion_group, criterion_main, Criterion};
+use euclid::{
+    dirval,
+    dssa::graph::{self, Memoization},
+    frontend::dir,
+    types::{NumValue, NumValueRefinement},
+};
+use kgraph_utils::{error::KgraphError, transformers::IntoDirValue};
+
+fn build_test_data<'a>(total_enabled: usize, total_pm_types: usize) -> graph::KnowledgeGraph<'a> {
+    use api_models::{admin::*, payment_methods::*};
+
+    let mut pms_enabled: Vec<PaymentMethodsEnabled> = Vec::new();
+
+    for _ in (0..total_enabled) {
+        let mut pm_types: Vec<RequestPaymentMethodTypes> = Vec::new();
+        for _ in (0..total_pm_types) {
+            pm_types.push(RequestPaymentMethodTypes {
+                payment_method_type: api_enums::PaymentMethodType::Credit,
+                payment_experience: None,
+                card_networks: Some(vec![
+                    api_enums::CardNetwork::Visa,
+                    api_enums::CardNetwork::Mastercard,
+                ]),
+                accepted_currencies: Some(AcceptedCurrencies::EnableOnly(vec![
+                    api_enums::Currency::USD,
+                    api_enums::Currency::INR,
+                ])),
+                accepted_countries: None,
+                minimum_amount: Some(10),
+                maximum_amount: Some(1000),
+                recurring_enabled: true,
+                installment_payment_enabled: true,
+            });
+        }
+
+        pms_enabled.push(PaymentMethodsEnabled {
+            payment_method: api_enums::PaymentMethod::Card,
+            payment_method_types: Some(pm_types),
+        });
+    }
+
+    let stripe_account = MerchantConnectorResponse {
+        connector_type: api_enums::ConnectorType::FizOperations,
+        connector_name: "stripe".to_string(),
+        merchant_connector_id: "something".to_string(),
+        connector_account_details: masking::Secret::new(serde_json::json!({})),
+        test_mode: None,
+        disabled: None,
+        metadata: None,
+        payment_methods_enabled: Some(pms_enabled),
+        business_country: Some(api_enums::CountryAlpha2::US),
+        business_label: Some("hello".to_string()),
+        connector_label: Some("something".to_string()),
+        business_sub_label: Some("something".to_string()),
+        frm_configs: None,
+        connector_webhook_details: None,
+        profile_id: None,
+        applepay_verified_domains: None,
+        pm_auth_config: None,
+    };
+
+    kgraph_utils::mca::make_mca_graph(vec![stripe_account]).expect("Failed graph construction")
+}
+
+fn evaluation(c: &mut Criterion) {
+    let small_graph = build_test_data(3, 8);
+    let big_graph = build_test_data(20, 20);
+
+    c.bench_function("MCA Small Graph Evaluation", |b| {
+        b.iter(|| {
+            small_graph.key_value_analysis(
+                dirval!(Connector = Stripe),
+                &graph::AnalysisContext::from_dir_values([
+                    dirval!(Connector = Stripe),
+                    dirval!(PaymentMethod = Card),
+                    dirval!(CardType = Credit),
+                    dirval!(CardNetwork = Visa),
+                    dirval!(PaymentCurrency = BWP),
+                    dirval!(PaymentAmount = 100),
+                ]),
+                &mut Memoization::new(),
+            );
+        });
+    });
+
+    c.bench_function("MCA Big Graph Evaluation", |b| {
+        b.iter(|| {
+            big_graph.key_value_analysis(
+                dirval!(Connector = Stripe),
+                &graph::AnalysisContext::from_dir_values([
+                    dirval!(Connector = Stripe),
+                    dirval!(PaymentMethod = Card),
+                    dirval!(CardType = Credit),
+                    dirval!(CardNetwork = Visa),
+                    dirval!(PaymentCurrency = BWP),
+                    dirval!(PaymentAmount = 100),
+                ]),
+                &mut Memoization::new(),
+            );
+        });
+    });
+}
+
+criterion_group!(benches, evaluation);
+criterion_main!(benches);
diff --git a/crates/kgraph_utils/src/error.rs b/crates/kgraph_utils/src/error.rs
new file mode 100644
index 000000000000..5a16c6375b06
--- /dev/null
+++ b/crates/kgraph_utils/src/error.rs
@@ -0,0 +1,14 @@
+use euclid::dssa::{graph::GraphError, types::AnalysisErrorType};
+
+#[derive(Debug, thiserror::Error, serde::Serialize)]
+#[serde(tag = "type", content = "info", rename_all = "snake_case")]
+pub enum KgraphError {
+    #[error("Invalid connector name encountered: '{0}'")]
+    InvalidConnectorName(String),
+    #[error("There was an error constructing the graph: {0}")]
+    GraphConstructionError(GraphError),
+    #[error("There was an error constructing the context")]
+    ContextConstructionError(AnalysisErrorType),
+    #[error("there was an unprecedented indexing error")]
+    IndexingError,
+}
diff --git a/crates/kgraph_utils/src/lib.rs b/crates/kgraph_utils/src/lib.rs
new file mode 100644
index 000000000000..eb8eef6dedb5
--- /dev/null
+++ b/crates/kgraph_utils/src/lib.rs
@@ -0,0 +1,3 @@
+pub mod error;
+pub mod mca;
+pub mod transformers;
diff --git a/crates/kgraph_utils/src/mca.rs b/crates/kgraph_utils/src/mca.rs
new file mode 100644
index 000000000000..34babd7a02bd
--- /dev/null
+++ b/crates/kgraph_utils/src/mca.rs
@@ -0,0 +1,739 @@
+use std::str::FromStr;
+
+use api_models::{
+    admin as admin_api, enums as api_enums, payment_methods::RequestPaymentMethodTypes,
+};
+use euclid::{
+    dssa::graph::{self, DomainIdentifier},
+    frontend::{
+        ast,
+        dir::{self, enums as dir_enums},
+    },
+    types::{NumValue, NumValueRefinement},
+};
+
+use crate::{error::KgraphError, transformers::IntoDirValue};
+
+pub const DOMAIN_IDENTIFIER: &str = "payment_methods_enabled_for_merchantconnectoraccount";
+
+fn compile_request_pm_types(
+    builder: &mut graph::KnowledgeGraphBuilder<'_>,
+    pm_types: RequestPaymentMethodTypes,
+    pm: api_enums::PaymentMethod,
+) -> Result<graph::NodeId, KgraphError> {
+    let mut agg_nodes: Vec<(graph::NodeId, graph::Relation, graph::Strength)> = Vec::new();
+
+    let pmt_info = "PaymentMethodType";
+    let pmt_id = builder
+        .make_value_node(
+            (pm_types.payment_method_type, pm)
+                .into_dir_value()
+                .map(Into::into)?,
+            Some(pmt_info),
+            vec![DomainIdentifier::new(DOMAIN_IDENTIFIER)],
+            None::<()>,
+        )
+        .map_err(KgraphError::GraphConstructionError)?;
+    agg_nodes.push((
+        pmt_id,
+        graph::Relation::Positive,
+        match pm_types.payment_method_type {
+            api_enums::PaymentMethodType::Credit | api_enums::PaymentMethodType::Debit => {
+                graph::Strength::Weak
+            }
+
+            _ => graph::Strength::Strong,
+        },
+    ));
+
+    if let Some(card_networks) = pm_types.card_networks {
+        if !card_networks.is_empty() {
+            let dir_vals: Vec<dir::DirValue> = card_networks
+                .into_iter()
+                .map(IntoDirValue::into_dir_value)
+                .collect::<Result<_, _>>()?;
+
+            let card_network_info = "Card Networks";
+            let card_network_id = builder
+                .make_in_aggregator(dir_vals, Some(card_network_info), None::<()>, Vec::new())
+                .map_err(KgraphError::GraphConstructionError)?;
+
+            agg_nodes.push((
+                card_network_id,
+                graph::Relation::Positive,
+                graph::Strength::Weak,
+            ));
+        }
+    }
+
+    let currencies_data = pm_types
+        .accepted_currencies
+        .and_then(|accepted_currencies| match accepted_currencies {
+            admin_api::AcceptedCurrencies::EnableOnly(curr) if !curr.is_empty() => Some((
+                curr.into_iter()
+                    .map(IntoDirValue::into_dir_value)
+                    .collect::<Result<_, _>>()
+                    .ok()?,
+                graph::Relation::Positive,
+            )),
+
+            admin_api::AcceptedCurrencies::DisableOnly(curr) if !curr.is_empty() => Some((
+                curr.into_iter()
+                    .map(IntoDirValue::into_dir_value)
+                    .collect::<Result<_, _>>()
+                    .ok()?,
+                graph::Relation::Negative,
+            )),
+
+            _ => None,
+        });
+
+    if let Some((currencies, relation)) = currencies_data {
+        let accepted_currencies_info = "Accepted Currencies";
+        let accepted_currencies_id = builder
+            .make_in_aggregator(
+                currencies,
+                Some(accepted_currencies_info),
+                None::<()>,
+                Vec::new(),
+            )
+            .map_err(KgraphError::GraphConstructionError)?;
+
+        agg_nodes.push((accepted_currencies_id, relation, graph::Strength::Strong));
+    }
+
+    let mut amount_nodes = Vec::with_capacity(2);
+
+    if let Some(min_amt) = pm_types.minimum_amount {
+        let num_val = NumValue {
+            number: min_amt.into(),
+            refinement: Some(NumValueRefinement::GreaterThanEqual),
+        };
+
+        let min_amt_info = "Minimum Amount";
+        let min_amt_id = builder
+            .make_value_node(
+                dir::DirValue::PaymentAmount(num_val).into(),
+                Some(min_amt_info),
+                vec![DomainIdentifier::new(DOMAIN_IDENTIFIER)],
+                None::<()>,
+            )
+            .map_err(KgraphError::GraphConstructionError)?;
+
+        amount_nodes.push(min_amt_id);
+    }
+
+    if let Some(max_amt) = pm_types.maximum_amount {
+        let num_val = NumValue {
+            number: max_amt.into(),
+            refinement: Some(NumValueRefinement::LessThanEqual),
+        };
+
+        let max_amt_info = "Maximum Amount";
+        let max_amt_id = builder
+            .make_value_node(
+                dir::DirValue::PaymentAmount(num_val).into(),
+                Some(max_amt_info),
+                vec![DomainIdentifier::new(DOMAIN_IDENTIFIER)],
+                None::<()>,
+            )
+            .map_err(KgraphError::GraphConstructionError)?;
+
+        amount_nodes.push(max_amt_id);
+    }
+
+    if !amount_nodes.is_empty() {
+        let zero_num_val = NumValue {
+            number: 0,
+            refinement: None,
+        };
+
+        let zero_amt_id = builder
+            .make_value_node(
+                dir::DirValue::PaymentAmount(zero_num_val).into(),
+                Some("zero_amount"),
+                vec![DomainIdentifier::new(DOMAIN_IDENTIFIER)],
+                None::<()>,
+            )
+            .map_err(KgraphError::GraphConstructionError)?;
+
+        let or_node_neighbor_id = if amount_nodes.len() == 1 {
+            amount_nodes
+                .get(0)
+                .copied()
+                .ok_or(KgraphError::IndexingError)?
+        } else {
+            let nodes = amount_nodes
+                .iter()
+                .copied()
+                .map(|node_id| (node_id, graph::Relation::Positive, graph::Strength::Strong))
+                .collect::<Vec<_>>();
+
+            builder
+                .make_all_aggregator(
+                    &nodes,
+                    Some("amount_constraint_aggregator"),
+                    None::<()>,
+                    vec![DomainIdentifier::new(DOMAIN_IDENTIFIER)],
+                )
+                .map_err(KgraphError::GraphConstructionError)?
+        };
+
+        let any_aggregator = builder
+            .make_any_aggregator(
+                &[
+                    (zero_amt_id, graph::Relation::Positive),
+                    (or_node_neighbor_id, graph::Relation::Positive),
+                ],
+                Some("zero_plus_limits_amount_aggregator"),
+                None::<()>,
+                vec![DomainIdentifier::new(DOMAIN_IDENTIFIER)],
+            )
+            .map_err(KgraphError::GraphConstructionError)?;
+
+        agg_nodes.push((
+            any_aggregator,
+            graph::Relation::Positive,
+            graph::Strength::Strong,
+        ));
+    }
+
+    let pmt_all_aggregator_info = "All Aggregator for PaymentMethodType";
+    builder
+        .make_all_aggregator(
+            &agg_nodes,
+            Some(pmt_all_aggregator_info),
+            None::<()>,
+            Vec::new(),
+        )
+        .map_err(KgraphError::GraphConstructionError)
+}
+
+fn compile_payment_method_enabled(
+    builder: &mut graph::KnowledgeGraphBuilder<'_>,
+    enabled: admin_api::PaymentMethodsEnabled,
+) -> Result<Option<graph::NodeId>, KgraphError> {
+    let agg_id = if !enabled
+        .payment_method_types
+        .as_ref()
+        .map(|v| v.is_empty())
+        .unwrap_or(true)
+    {
+        let pm_info = "PaymentMethod";
+        let pm_id = builder
+            .make_value_node(
+                enabled.payment_method.into_dir_value().map(Into::into)?,
+                Some(pm_info),
+                vec![DomainIdentifier::new(DOMAIN_IDENTIFIER)],
+                None::<()>,
+            )
+            .map_err(KgraphError::GraphConstructionError)?;
+
+        let mut agg_nodes: Vec<(graph::NodeId, graph::Relation)> = Vec::new();
+
+        if let Some(pm_types) = enabled.payment_method_types {
+            for pm_type in pm_types {
+                let node_id = compile_request_pm_types(builder, pm_type, enabled.payment_method)?;
+                agg_nodes.push((node_id, graph::Relation::Positive));
+            }
+        }
+
+        let any_aggregator_info = "Any aggregation for PaymentMethodsType";
+        let pm_type_agg_id = builder
+            .make_any_aggregator(
+                &agg_nodes,
+                Some(any_aggregator_info),
+                None::<()>,
+                Vec::new(),
+            )
+            .map_err(KgraphError::GraphConstructionError)?;
+
+        let all_aggregator_info = "All aggregation for PaymentMethod";
+        let enabled_pm_agg_id = builder
+            .make_all_aggregator(
+                &[
+                    (pm_id, graph::Relation::Positive, graph::Strength::Strong),
+                    (
+                        pm_type_agg_id,
+                        graph::Relation::Positive,
+                        graph::Strength::Strong,
+                    ),
+                ],
+                Some(all_aggregator_info),
+                None::<()>,
+                Vec::new(),
+            )
+            .map_err(KgraphError::GraphConstructionError)?;
+
+        Some(enabled_pm_agg_id)
+    } else {
+        None
+    };
+
+    Ok(agg_id)
+}
+
+fn compile_merchant_connector_graph(
+    builder: &mut graph::KnowledgeGraphBuilder<'_>,
+    mca: admin_api::MerchantConnectorResponse,
+) -> Result<(), KgraphError> {
+    let connector = dir_enums::Connector::from_str(&mca.connector_name)
+        .map_err(|_| KgraphError::InvalidConnectorName(mca.connector_name.clone()))?;
+
+    let mut agg_nodes: Vec<(graph::NodeId, graph::Relation)> = Vec::new();
+
+    if let Some(pms_enabled) = mca.payment_methods_enabled {
+        for pm_enabled in pms_enabled {
+            let maybe_pm_enabled_id = compile_payment_method_enabled(builder, pm_enabled)?;
+            if let Some(pm_enabled_id) = maybe_pm_enabled_id {
+                agg_nodes.push((pm_enabled_id, graph::Relation::Positive));
+            }
+        }
+    }
+
+    let aggregator_info = "Available Payment methods for connector";
+    let pms_enabled_agg_id = builder
+        .make_any_aggregator(&agg_nodes, Some(aggregator_info), None::<()>, Vec::new())
+        .map_err(KgraphError::GraphConstructionError)?;
+
+    let connector_dir_val = dir::DirValue::Connector(Box::new(ast::ConnectorChoice {
+        connector,
+        #[cfg(not(feature = "connector_choice_mca_id"))]
+        sub_label: mca.business_sub_label,
+    }));
+
+    let connector_info = "Connector";
+    let connector_node_id = builder
+        .make_value_node(
+            connector_dir_val.into(),
+            Some(connector_info),
+            vec![DomainIdentifier::new(DOMAIN_IDENTIFIER)],
+            None::<()>,
+        )
+        .map_err(KgraphError::GraphConstructionError)?;
+
+    builder
+        .make_edge(
+            pms_enabled_agg_id,
+            connector_node_id,
+            graph::Strength::Normal,
+            graph::Relation::Positive,
+        )
+        .map_err(KgraphError::GraphConstructionError)?;
+
+    Ok(())
+}
+
+pub fn make_mca_graph<'a>(
+    accts: Vec<admin_api::MerchantConnectorResponse>,
+) -> Result<graph::KnowledgeGraph<'a>, KgraphError> {
+    let mut builder = graph::KnowledgeGraphBuilder::new();
+    let _domain = builder.make_domain(
+        DomainIdentifier::new(DOMAIN_IDENTIFIER),
+        "Payment methods enabled for MerchantConnectorAccount".to_string(),
+    );
+    for acct in accts {
+        compile_merchant_connector_graph(&mut builder, acct)?;
+    }
+
+    Ok(builder.build())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::expect_used)]
+
+    use api_models::enums as api_enums;
+    use euclid::{
+        dirval,
+        dssa::graph::{AnalysisContext, Memoization},
+    };
+
+    use super::*;
+
+    fn build_test_data<'a>() -> graph::KnowledgeGraph<'a> {
+        use api_models::{admin::*, payment_methods::*};
+
+        let stripe_account = MerchantConnectorResponse {
+            connector_type: api_enums::ConnectorType::FizOperations,
+            connector_name: "stripe".to_string(),
+            merchant_connector_id: "something".to_string(),
+            business_country: Some(api_enums::CountryAlpha2::US),
+            connector_label: Some("something".to_string()),
+            business_label: Some("food".to_string()),
+            business_sub_label: None,
+            connector_account_details: masking::Secret::new(serde_json::json!({})),
+            test_mode: None,
+            disabled: None,
+            metadata: None,
+            payment_methods_enabled: Some(vec![PaymentMethodsEnabled {
+                payment_method: api_enums::PaymentMethod::Card,
+                payment_method_types: Some(vec![
+                    RequestPaymentMethodTypes {
+                        payment_method_type: api_enums::PaymentMethodType::Credit,
+                        payment_experience: None,
+                        card_networks: Some(vec![
+                            api_enums::CardNetwork::Visa,
+                            api_enums::CardNetwork::Mastercard,
+                        ]),
+                        accepted_currencies: Some(AcceptedCurrencies::EnableOnly(vec![
+                            api_enums::Currency::USD,
+                            api_enums::Currency::INR,
+                        ])),
+                        accepted_countries: None,
+                        minimum_amount: Some(10),
+                        maximum_amount: Some(1000),
+                        recurring_enabled: true,
+                        installment_payment_enabled: true,
+                    },
+                    RequestPaymentMethodTypes {
+                        payment_method_type: api_enums::PaymentMethodType::Debit,
+                        payment_experience: None,
+                        card_networks: Some(vec![
+                            api_enums::CardNetwork::Maestro,
+                            api_enums::CardNetwork::JCB,
+                        ]),
+                        accepted_currencies: Some(AcceptedCurrencies::EnableOnly(vec![
+                            api_enums::Currency::GBP,
+                            api_enums::Currency::PHP,
+                        ])),
+                        accepted_countries: None,
+                        minimum_amount: Some(10),
+                        maximum_amount: Some(1000),
+                        recurring_enabled: true,
+                        installment_payment_enabled: true,
+                    },
+                ]),
+            }]),
+            frm_configs: None,
+            connector_webhook_details: None,
+            profile_id: None,
+            applepay_verified_domains: None,
+            pm_auth_config: None,
+        };
+
+        make_mca_graph(vec![stripe_account]).expect("Failed graph construction")
+    }
+
+    #[test]
+    fn test_credit_card_success_case() {
+        let graph = build_test_data();
+
+        let result = graph.key_value_analysis(
+            dirval!(Connector = Stripe),
+            &AnalysisContext::from_dir_values([
+                dirval!(Connector = Stripe),
+                dirval!(PaymentMethod = Card),
+                dirval!(CardType = Credit),
+                dirval!(CardNetwork = Visa),
+                dirval!(PaymentCurrency = USD),
+                dirval!(PaymentAmount = 100),
+            ]),
+            &mut Memoization::new(),
+        );
+
+        assert!(result.is_ok());
+    }
+
+    #[test]
+    fn test_debit_card_success_case() {
+        let graph = build_test_data();
+
+        let result = graph.key_value_analysis(
+            dirval!(Connector = Stripe),
+            &AnalysisContext::from_dir_values([
+                dirval!(Connector = Stripe),
+                dirval!(PaymentMethod = Card),
+                dirval!(CardType = Debit),
+                dirval!(CardNetwork = Maestro),
+                dirval!(PaymentCurrency = GBP),
+                dirval!(PaymentAmount = 100),
+            ]),
+            &mut Memoization::new(),
+        );
+
+        assert!(result.is_ok());
+    }
+
+    #[test]
+    fn test_single_mismatch_failure_case() {
+        let graph = build_test_data();
+
+        let result = graph.key_value_analysis(
+            dirval!(Connector = Stripe),
+            &AnalysisContext::from_dir_values([
+                dirval!(Connector = Stripe),
+                dirval!(PaymentMethod = Card),
+                dirval!(CardType = Debit),
+                dirval!(CardNetwork = DinersClub),
+                dirval!(PaymentCurrency = GBP),
+                dirval!(PaymentAmount = 100),
+            ]),
+            &mut Memoization::new(),
+        );
+
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_amount_mismatch_failure_case() {
+        let graph = build_test_data();
+
+        let result = graph.key_value_analysis(
+            dirval!(Connector = Stripe),
+            &AnalysisContext::from_dir_values([
+                dirval!(Connector = Stripe),
+                dirval!(PaymentMethod = Card),
+                dirval!(CardType = Debit),
+                dirval!(CardNetwork = Visa),
+                dirval!(PaymentCurrency = GBP),
+                dirval!(PaymentAmount = 7),
+            ]),
+            &mut Memoization::new(),
+        );
+
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_incomplete_data_failure_case() {
+        let graph = build_test_data();
+
+        let result = graph.key_value_analysis(
+            dirval!(Connector = Stripe),
+            &AnalysisContext::from_dir_values([
+                dirval!(Connector = Stripe),
+                dirval!(PaymentMethod = Card),
+                dirval!(CardType = Debit),
+                dirval!(PaymentCurrency = GBP),
+                dirval!(PaymentAmount = 7),
+            ]),
+            &mut Memoization::new(),
+        );
+
+        //println!("{:#?}", result);
+        //println!("{}", serde_json::to_string_pretty(&result).expect("Hello"));
+
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_incomplete_data_failure_case2() {
+        let graph = build_test_data();
+
+        let result = graph.key_value_analysis(
+            dirval!(Connector = Stripe),
+            &AnalysisContext::from_dir_values([
+                dirval!(Connector = Stripe),
+                dirval!(CardType = Debit),
+                dirval!(CardNetwork = Visa),
+                dirval!(PaymentCurrency = GBP),
+                dirval!(PaymentAmount = 100),
+            ]),
+            &mut Memoization::new(),
+        );
+
+        //println!("{:#?}", result);
+        //println!("{}", serde_json::to_string_pretty(&result).expect("Hello"));
+
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_sandbox_applepay_bug_usecase() {
+        let value = serde_json::json!([
+            {
+                "connector_type": "payment_processor",
+                "connector_name": "bluesnap",
+                "merchant_connector_id": "REDACTED",
+                "connector_account_details": {
+                    "auth_type": "BodyKey",
+                    "api_key": "REDACTED",
+                    "key1": "REDACTED"
+                },
+                "test_mode": true,
+                "disabled": false,
+                "payment_methods_enabled": [
+                    {
+                        "payment_method": "card",
+                        "payment_method_types": [
+                            {
+                                "payment_method_type": "credit",
+                                "payment_experience": null,
+                                "card_networks": [
+                                    "Mastercard",
+                                    "Visa",
+                                    "AmericanExpress",
+                                    "JCB",
+                                    "DinersClub",
+                                    "Discover",
+                                    "CartesBancaires",
+                                    "UnionPay"
+                                ],
+                                "accepted_currencies": null,
+                                "accepted_countries": null,
+                                "minimum_amount": 1,
+                                "maximum_amount": 68607706,
+                                "recurring_enabled": true,
+                                "installment_payment_enabled": true
+                            },
+                            {
+                                "payment_method_type": "debit",
+                                "payment_experience": null,
+                                "card_networks": [
+                                    "Mastercard",
+                                    "Visa",
+                                    "Interac",
+                                    "AmericanExpress",
+                                    "JCB",
+                                    "DinersClub",
+                                    "Discover",
+                                    "CartesBancaires",
+                                    "UnionPay"
+                                ],
+                                "accepted_currencies": null,
+                                "accepted_countries": null,
+                                "minimum_amount": 1,
+                                "maximum_amount": 68607706,
+                                "recurring_enabled": true,
+                                "installment_payment_enabled": true
+                            }
+                        ]
+                    },
+                    {
+                        "payment_method": "wallet",
+                        "payment_method_types": [
+                            {
+                                "payment_method_type": "google_pay",
+                                "payment_experience": "invoke_sdk_client",
+                                "card_networks": null,
+                                "accepted_currencies": null,
+                                "accepted_countries": null,
+                                "minimum_amount": 1,
+                                "maximum_amount": 68607706,
+                                "recurring_enabled": true,
+                                "installment_payment_enabled": true
+                            }
+                        ]
+                    }
+                ],
+                "metadata": {},
+                "business_country": "US",
+                "business_label": "default",
+                "business_sub_label": null,
+                "frm_configs": null
+            },
+            {
+                "connector_type": "payment_processor",
+                "connector_name": "stripe",
+                "merchant_connector_id": "REDACTED",
+                "connector_account_details": {
+                    "auth_type": "HeaderKey",
+                    "api_key": "REDACTED"
+                },
+                "test_mode": true,
+                "disabled": false,
+                "payment_methods_enabled": [
+                    {
+                        "payment_method": "card",
+                        "payment_method_types": [
+                            {
+                                "payment_method_type": "credit",
+                                "payment_experience": null,
+                                "card_networks": [
+                                    "Mastercard",
+                                    "Visa",
+                                    "AmericanExpress",
+                                    "JCB",
+                                    "DinersClub",
+                                    "Discover",
+                                    "CartesBancaires",
+                                    "UnionPay"
+                                ],
+                                "accepted_currencies": null,
+                                "accepted_countries": null,
+                                "minimum_amount": 1,
+                                "maximum_amount": 68607706,
+                                "recurring_enabled": true,
+                                "installment_payment_enabled": true
+                            },
+                            {
+                                "payment_method_type": "debit",
+                                "payment_experience": null,
+                                "card_networks": [
+                                    "Mastercard",
+                                    "Visa",
+                                    "Interac",
+                                    "AmericanExpress",
+                                    "JCB",
+                                    "DinersClub",
+                                    "Discover",
+                                    "CartesBancaires",
+                                    "UnionPay"
+                                ],
+                                "accepted_currencies": null,
+                                "accepted_countries": null,
+                                "minimum_amount": 1,
+                                "maximum_amount": 68607706,
+                                "recurring_enabled": true,
+                                "installment_payment_enabled": true
+                            }
+                        ]
+                    },
+                    {
+                        "payment_method": "wallet",
+                        "payment_method_types": [
+                            {
+                                "payment_method_type": "apple_pay",
+                                "payment_experience": "invoke_sdk_client",
+                                "card_networks": null,
+                                "accepted_currencies": null,
+                                "accepted_countries": null,
+                                "minimum_amount": 1,
+                                "maximum_amount": 68607706,
+                                "recurring_enabled": true,
+                                "installment_payment_enabled": true
+                            }
+                        ]
+                    },
+                    {
+                        "payment_method": "pay_later",
+                        "payment_method_types": []
+                    }
+                ],
+                "metadata": {},
+                "business_country": "US",
+                "business_label": "default",
+                "business_sub_label": null,
+                "frm_configs": null
+            }
+        ]);
+
+        let data: Vec<admin_api::MerchantConnectorResponse> =
+            serde_json::from_value(value).expect("data");
+
+        let graph = make_mca_graph(data).expect("graph");
+        let context = AnalysisContext::from_dir_values([
+            dirval!(Connector = Stripe),
+            dirval!(PaymentAmount = 212),
+            dirval!(PaymentCurrency = ILS),
+            dirval!(PaymentMethod = Wallet),
+            dirval!(WalletType = ApplePay),
+        ]);
+
+        let result = graph.key_value_analysis(
+            dirval!(Connector = Stripe),
+            &context,
+            &mut Memoization::new(),
+        );
+
+        assert!(result.is_ok(), "stripe validation failed");
+
+        let result = graph.key_value_analysis(
+            dirval!(Connector = Bluesnap),
+            &context,
+            &mut Memoization::new(),
+        );
+        assert!(result.is_err(), "bluesnap validation failed");
+    }
+}
diff --git a/crates/kgraph_utils/src/transformers.rs b/crates/kgraph_utils/src/transformers.rs
new file mode 100644
index 000000000000..3d32cce38bd8
--- /dev/null
+++ b/crates/kgraph_utils/src/transformers.rs
@@ -0,0 +1,724 @@
+use api_models::enums as api_enums;
+use euclid::{
+    backend::BackendInput,
+    dirval,
+    dssa::types::AnalysisErrorType,
+    frontend::{ast, dir},
+    types::{NumValue, StrValue},
+};
+
+use crate::error::KgraphError;
+
+pub trait IntoContext {
+    fn into_context(self) -> Result<Vec<dir::DirValue>, KgraphError>;
+}
+
+impl IntoContext for BackendInput {
+    fn into_context(self) -> Result<Vec<dir::DirValue>, KgraphError> {
+        let mut ctx: Vec<dir::DirValue> = Vec::new();
+
+        ctx.push(dir::DirValue::PaymentAmount(NumValue {
+            number: self.payment.amount,
+            refinement: None,
+        }));
+
+        ctx.push(dir::DirValue::PaymentCurrency(self.payment.currency));
+
+        if let Some(auth_type) = self.payment.authentication_type {
+            ctx.push(dir::DirValue::AuthenticationType(auth_type));
+        }
+
+        if let Some(capture_method) = self.payment.capture_method {
+            ctx.push(dir::DirValue::CaptureMethod(capture_method));
+        }
+
+        if let Some(business_country) = self.payment.business_country {
+            ctx.push(dir::DirValue::BusinessCountry(business_country));
+        }
+        if let Some(business_label) = self.payment.business_label {
+            ctx.push(dir::DirValue::BusinessLabel(StrValue {
+                value: business_label,
+            }));
+        }
+        if let Some(billing_country) = self.payment.billing_country {
+            ctx.push(dir::DirValue::BillingCountry(billing_country));
+        }
+
+        if let Some(payment_method) = self.payment_method.payment_method {
+            ctx.push(dir::DirValue::PaymentMethod(payment_method));
+        }
+
+        if let (Some(pm_type), Some(payment_method)) = (
+            self.payment_method.payment_method_type,
+            self.payment_method.payment_method,
+        ) {
+            ctx.push((pm_type, payment_method).into_dir_value()?)
+        }
+
+        if let Some(card_network) = self.payment_method.card_network {
+            ctx.push(dir::DirValue::CardNetwork(card_network));
+        }
+        if let Some(setup_future_usage) = self.payment.setup_future_usage {
+            ctx.push(dir::DirValue::SetupFutureUsage(setup_future_usage));
+        }
+        if let Some(mandate_acceptance_type) = self.mandate.mandate_acceptance_type {
+            ctx.push(dir::DirValue::MandateAcceptanceType(
+                mandate_acceptance_type,
+            ));
+        }
+        if let Some(mandate_type) = self.mandate.mandate_type {
+            ctx.push(dir::DirValue::MandateType(mandate_type));
+        }
+        if let Some(payment_type) = self.mandate.payment_type {
+            ctx.push(dir::DirValue::PaymentType(payment_type));
+        }
+
+        Ok(ctx)
+    }
+}
+
+pub trait IntoDirValue {
+    fn into_dir_value(self) -> Result<dir::DirValue, KgraphError>;
+}
+
+impl IntoDirValue for ast::ConnectorChoice {
+    fn into_dir_value(self) -> Result<dir::DirValue, KgraphError> {
+        Ok(dir::DirValue::Connector(Box::new(self)))
+    }
+}
+
+impl IntoDirValue for api_enums::PaymentMethod {
+    fn into_dir_value(self) -> Result<dir::DirValue, KgraphError> {
+        match self {
+            Self::Card => Ok(dirval!(PaymentMethod = Card)),
+            Self::Wallet => Ok(dirval!(PaymentMethod = Wallet)),
+            Self::PayLater => Ok(dirval!(PaymentMethod = PayLater)),
+            Self::BankRedirect => Ok(dirval!(PaymentMethod = BankRedirect)),
+            Self::Crypto => Ok(dirval!(PaymentMethod = Crypto)),
+            Self::BankDebit => Ok(dirval!(PaymentMethod = BankDebit)),
+            Self::BankTransfer => Ok(dirval!(PaymentMethod = BankTransfer)),
+            Self::Reward => Ok(dirval!(PaymentMethod = Reward)),
+            Self::Upi => Ok(dirval!(PaymentMethod = Upi)),
+            Self::Voucher => Ok(dirval!(PaymentMethod = Voucher)),
+            Self::GiftCard => Ok(dirval!(PaymentMethod = GiftCard)),
+            Self::CardRedirect => Ok(dirval!(PaymentMethod = CardRedirect)),
+        }
+    }
+}
+
+impl IntoDirValue for api_enums::AuthenticationType {
+    fn into_dir_value(self) -> Result<dir::DirValue, KgraphError> {
+        match self {
+            Self::ThreeDs => Ok(dirval!(AuthenticationType = ThreeDs)),
+            Self::NoThreeDs => Ok(dirval!(AuthenticationType = NoThreeDs)),
+        }
+    }
+}
+
+impl IntoDirValue for api_enums::FutureUsage {
+    fn into_dir_value(self) -> Result<dir::DirValue, KgraphError> {
+        match self {
+            Self::OnSession => Ok(dirval!(SetupFutureUsage = OnSession)),
+            Self::OffSession => Ok(dirval!(SetupFutureUsage = OffSession)),
+        }
+    }
+}
+
+impl IntoDirValue for (api_enums::PaymentMethodType, api_enums::PaymentMethod) {
+    fn into_dir_value(self) -> Result<dir::DirValue, KgraphError> {
+        match self.0 {
+            api_enums::PaymentMethodType::Credit => Ok(dirval!(CardType = Credit)),
+            api_enums::PaymentMethodType::Debit => Ok(dirval!(CardType = Debit)),
+            api_enums::PaymentMethodType::Giropay => Ok(dirval!(BankRedirectType = Giropay)),
+            api_enums::PaymentMethodType::Ideal => Ok(dirval!(BankRedirectType = Ideal)),
+            api_enums::PaymentMethodType::Sofort => Ok(dirval!(BankRedirectType = Sofort)),
+            api_enums::PaymentMethodType::Eps => Ok(dirval!(BankRedirectType = Eps)),
+            api_enums::PaymentMethodType::Klarna => Ok(dirval!(PayLaterType = Klarna)),
+            api_enums::PaymentMethodType::Affirm => Ok(dirval!(PayLaterType = Affirm)),
+            api_enums::PaymentMethodType::AfterpayClearpay => {
+                Ok(dirval!(PayLaterType = AfterpayClearpay))
+            }
+            api_enums::PaymentMethodType::GooglePay => Ok(dirval!(WalletType = GooglePay)),
+            api_enums::PaymentMethodType::ApplePay => Ok(dirval!(WalletType = ApplePay)),
+            api_enums::PaymentMethodType::Paypal => Ok(dirval!(WalletType = Paypal)),
+            api_enums::PaymentMethodType::CryptoCurrency => {
+                Ok(dirval!(CryptoType = CryptoCurrency))
+            }
+            api_enums::PaymentMethodType::Ach => match self.1 {
+                api_enums::PaymentMethod::BankDebit => Ok(dirval!(BankDebitType = Ach)),
+                api_enums::PaymentMethod::BankTransfer => Ok(dirval!(BankTransferType = Ach)),
+                api_enums::PaymentMethod::BankRedirect
+                | api_enums::PaymentMethod::Card
+                | api_enums::PaymentMethod::CardRedirect
+                | api_enums::PaymentMethod::PayLater
+                | api_enums::PaymentMethod::Wallet
+                | api_enums::PaymentMethod::Crypto
+                | api_enums::PaymentMethod::Reward
+                | api_enums::PaymentMethod::Upi
+                | api_enums::PaymentMethod::Voucher
+                | api_enums::PaymentMethod::GiftCard => Err(KgraphError::ContextConstructionError(
+                    AnalysisErrorType::NotSupported,
+                )),
+            },
+            api_enums::PaymentMethodType::Bacs => match self.1 {
+                api_enums::PaymentMethod::BankDebit => Ok(dirval!(BankDebitType = Bacs)),
+                api_enums::PaymentMethod::BankTransfer => Ok(dirval!(BankTransferType = Bacs)),
+                api_enums::PaymentMethod::BankRedirect
+                | api_enums::PaymentMethod::Card
+                | api_enums::PaymentMethod::CardRedirect
+                | api_enums::PaymentMethod::PayLater
+                | api_enums::PaymentMethod::Wallet
+                | api_enums::PaymentMethod::Crypto
+                | api_enums::PaymentMethod::Reward
+                | api_enums::PaymentMethod::Upi
+                | api_enums::PaymentMethod::Voucher
+                | api_enums::PaymentMethod::GiftCard => Err(KgraphError::ContextConstructionError(
+                    AnalysisErrorType::NotSupported,
+                )),
+            },
+            api_enums::PaymentMethodType::Becs => Ok(dirval!(BankDebitType = Becs)),
+            api_enums::PaymentMethodType::Sepa => match self.1 {
+                api_enums::PaymentMethod::BankDebit => Ok(dirval!(BankDebitType = Sepa)),
+                api_enums::PaymentMethod::BankTransfer => Ok(dirval!(BankTransferType = Sepa)),
+                api_enums::PaymentMethod::BankRedirect
+                | api_enums::PaymentMethod::Card
+                | api_enums::PaymentMethod::CardRedirect
+                | api_enums::PaymentMethod::PayLater
+                | api_enums::PaymentMethod::Wallet
+                | api_enums::PaymentMethod::Crypto
+                | api_enums::PaymentMethod::Reward
+                | api_enums::PaymentMethod::Upi
+                | api_enums::PaymentMethod::Voucher
+                | api_enums::PaymentMethod::GiftCard => Err(KgraphError::ContextConstructionError(
+                    AnalysisErrorType::NotSupported,
+                )),
+            },
+            api_enums::PaymentMethodType::AliPay => Ok(dirval!(WalletType = AliPay)),
+            api_enums::PaymentMethodType::AliPayHk => Ok(dirval!(WalletType = AliPayHk)),
+            api_enums::PaymentMethodType::BancontactCard => {
+                Ok(dirval!(BankRedirectType = BancontactCard))
+            }
+            api_enums::PaymentMethodType::Blik => Ok(dirval!(BankRedirectType = Blik)),
+            api_enums::PaymentMethodType::MbWay => Ok(dirval!(WalletType = MbWay)),
+            api_enums::PaymentMethodType::MobilePay => Ok(dirval!(WalletType = MobilePay)),
+            api_enums::PaymentMethodType::Cashapp => Ok(dirval!(WalletType = Cashapp)),
+            api_enums::PaymentMethodType::Multibanco => Ok(dirval!(BankTransferType = Multibanco)),
+            api_enums::PaymentMethodType::Pix => Ok(dirval!(BankTransferType = Pix)),
+            api_enums::PaymentMethodType::Pse => Ok(dirval!(BankTransferType = Pse)),
+            api_enums::PaymentMethodType::Interac => Ok(dirval!(BankRedirectType = Interac)),
+            api_enums::PaymentMethodType::OnlineBankingCzechRepublic => {
+                Ok(dirval!(BankRedirectType = OnlineBankingCzechRepublic))
+            }
+            api_enums::PaymentMethodType::OnlineBankingFinland => {
+                Ok(dirval!(BankRedirectType = OnlineBankingFinland))
+            }
+            api_enums::PaymentMethodType::OnlineBankingPoland => {
+                Ok(dirval!(BankRedirectType = OnlineBankingPoland))
+            }
+            api_enums::PaymentMethodType::OnlineBankingSlovakia => {
+                Ok(dirval!(BankRedirectType = OnlineBankingSlovakia))
+            }
+            api_enums::PaymentMethodType::Swish => Ok(dirval!(WalletType = Swish)),
+            api_enums::PaymentMethodType::Trustly => Ok(dirval!(BankRedirectType = Trustly)),
+            api_enums::PaymentMethodType::Bizum => Ok(dirval!(BankRedirectType = Bizum)),
+
+            api_enums::PaymentMethodType::PayBright => Ok(dirval!(PayLaterType = PayBright)),
+            api_enums::PaymentMethodType::Walley => Ok(dirval!(PayLaterType = Walley)),
+            api_enums::PaymentMethodType::Przelewy24 => Ok(dirval!(BankRedirectType = Przelewy24)),
+            api_enums::PaymentMethodType::WeChatPay => Ok(dirval!(WalletType = WeChatPay)),
+
+            api_enums::PaymentMethodType::ClassicReward => Ok(dirval!(RewardType = ClassicReward)),
+            api_enums::PaymentMethodType::Evoucher => Ok(dirval!(RewardType = Evoucher)),
+            api_enums::PaymentMethodType::UpiCollect => Ok(dirval!(UpiType = UpiCollect)),
+            api_enums::PaymentMethodType::SamsungPay => Ok(dirval!(WalletType = SamsungPay)),
+            api_enums::PaymentMethodType::GoPay => Ok(dirval!(WalletType = GoPay)),
+            api_enums::PaymentMethodType::KakaoPay => Ok(dirval!(WalletType = KakaoPay)),
+            api_enums::PaymentMethodType::Twint => Ok(dirval!(WalletType = Twint)),
+            api_enums::PaymentMethodType::Gcash => Ok(dirval!(WalletType = Gcash)),
+            api_enums::PaymentMethodType::Vipps => Ok(dirval!(WalletType = Vipps)),
+            api_enums::PaymentMethodType::Momo => Ok(dirval!(WalletType = Momo)),
+            api_enums::PaymentMethodType::Alma => Ok(dirval!(PayLaterType = Alma)),
+            api_enums::PaymentMethodType::Dana => Ok(dirval!(WalletType = Dana)),
+            api_enums::PaymentMethodType::OnlineBankingFpx => {
+                Ok(dirval!(BankRedirectType = OnlineBankingFpx))
+            }
+            api_enums::PaymentMethodType::OnlineBankingThailand => {
+                Ok(dirval!(BankRedirectType = OnlineBankingThailand))
+            }
+            api_enums::PaymentMethodType::TouchNGo => Ok(dirval!(WalletType = TouchNGo)),
+            api_enums::PaymentMethodType::Atome => Ok(dirval!(PayLaterType = Atome)),
+            api_enums::PaymentMethodType::Boleto => Ok(dirval!(VoucherType = Boleto)),
+            api_enums::PaymentMethodType::Efecty => Ok(dirval!(VoucherType = Efecty)),
+            api_enums::PaymentMethodType::PagoEfectivo => Ok(dirval!(VoucherType = PagoEfectivo)),
+            api_enums::PaymentMethodType::RedCompra => Ok(dirval!(VoucherType = RedCompra)),
+            api_enums::PaymentMethodType::RedPagos => Ok(dirval!(VoucherType = RedPagos)),
+            api_enums::PaymentMethodType::Alfamart => Ok(dirval!(VoucherType = Alfamart)),
+            api_enums::PaymentMethodType::BcaBankTransfer => {
+                Ok(dirval!(BankTransferType = BcaBankTransfer))
+            }
+            api_enums::PaymentMethodType::BniVa => Ok(dirval!(BankTransferType = BniVa)),
+            api_enums::PaymentMethodType::BriVa => Ok(dirval!(BankTransferType = BriVa)),
+            api_enums::PaymentMethodType::CimbVa => Ok(dirval!(BankTransferType = CimbVa)),
+            api_enums::PaymentMethodType::DanamonVa => Ok(dirval!(BankTransferType = DanamonVa)),
+            api_enums::PaymentMethodType::Indomaret => Ok(dirval!(VoucherType = Indomaret)),
+            api_enums::PaymentMethodType::MandiriVa => Ok(dirval!(BankTransferType = MandiriVa)),
+            api_enums::PaymentMethodType::PermataBankTransfer => {
+                Ok(dirval!(BankTransferType = PermataBankTransfer))
+            }
+            api_enums::PaymentMethodType::PaySafeCard => Ok(dirval!(GiftCardType = PaySafeCard)),
+            api_enums::PaymentMethodType::SevenEleven => Ok(dirval!(VoucherType = SevenEleven)),
+            api_enums::PaymentMethodType::Lawson => Ok(dirval!(VoucherType = Lawson)),
+            api_enums::PaymentMethodType::MiniStop => Ok(dirval!(VoucherType = MiniStop)),
+            api_enums::PaymentMethodType::FamilyMart => Ok(dirval!(VoucherType = FamilyMart)),
+            api_enums::PaymentMethodType::Seicomart => Ok(dirval!(VoucherType = Seicomart)),
+            api_enums::PaymentMethodType::PayEasy => Ok(dirval!(VoucherType = PayEasy)),
+            api_enums::PaymentMethodType::Givex => Ok(dirval!(GiftCardType = Givex)),
+            api_enums::PaymentMethodType::Benefit => Ok(dirval!(CardRedirectType = Benefit)),
+            api_enums::PaymentMethodType::Knet => Ok(dirval!(CardRedirectType = Knet)),
+            api_enums::PaymentMethodType::OpenBankingUk => {
+                Ok(dirval!(BankRedirectType = OpenBankingUk))
+            }
+            api_enums::PaymentMethodType::MomoAtm => Ok(dirval!(CardRedirectType = MomoAtm)),
+            api_enums::PaymentMethodType::Oxxo => Ok(dirval!(VoucherType = Oxxo)),
+        }
+    }
+}
+
+impl IntoDirValue for api_enums::CardNetwork {
+    fn into_dir_value(self) -> Result<dir::DirValue, KgraphError> {
+        match self {
+            Self::Visa => Ok(dirval!(CardNetwork = Visa)),
+            Self::Mastercard => Ok(dirval!(CardNetwork = Mastercard)),
+            Self::AmericanExpress => Ok(dirval!(CardNetwork = AmericanExpress)),
+            Self::JCB => Ok(dirval!(CardNetwork = JCB)),
+            Self::DinersClub => Ok(dirval!(CardNetwork = DinersClub)),
+            Self::Discover => Ok(dirval!(CardNetwork = Discover)),
+            Self::CartesBancaires => Ok(dirval!(CardNetwork = CartesBancaires)),
+            Self::UnionPay => Ok(dirval!(CardNetwork = UnionPay)),
+            Self::Interac => Ok(dirval!(CardNetwork = Interac)),
+            Self::RuPay => Ok(dirval!(CardNetwork = RuPay)),
+            Self::Maestro => Ok(dirval!(CardNetwork = Maestro)),
+        }
+    }
+}
+
+impl IntoDirValue for api_enums::Currency {
+    fn into_dir_value(self) -> Result<dir::DirValue, KgraphError> {
+        match self {
+            Self::AED => Ok(dirval!(PaymentCurrency = AED)),
+            Self::ALL => Ok(dirval!(PaymentCurrency = ALL)),
+            Self::AMD => Ok(dirval!(PaymentCurrency = AMD)),
+            Self::ANG => Ok(dirval!(PaymentCurrency = ANG)),
+            Self::ARS => Ok(dirval!(PaymentCurrency = ARS)),
+            Self::AUD => Ok(dirval!(PaymentCurrency = AUD)),
+            Self::AWG => Ok(dirval!(PaymentCurrency = AWG)),
+            Self::AZN => Ok(dirval!(PaymentCurrency = AZN)),
+            Self::BBD => Ok(dirval!(PaymentCurrency = BBD)),
+            Self::BDT => Ok(dirval!(PaymentCurrency = BDT)),
+            Self::BHD => Ok(dirval!(PaymentCurrency = BHD)),
+            Self::BIF => Ok(dirval!(PaymentCurrency = BIF)),
+            Self::BMD => Ok(dirval!(PaymentCurrency = BMD)),
+            Self::BND => Ok(dirval!(PaymentCurrency = BND)),
+            Self::BOB => Ok(dirval!(PaymentCurrency = BOB)),
+            Self::BRL => Ok(dirval!(PaymentCurrency = BRL)),
+            Self::BSD => Ok(dirval!(PaymentCurrency = BSD)),
+            Self::BWP => Ok(dirval!(PaymentCurrency = BWP)),
+            Self::BZD => Ok(dirval!(PaymentCurrency = BZD)),
+            Self::CAD => Ok(dirval!(PaymentCurrency = CAD)),
+            Self::CHF => Ok(dirval!(PaymentCurrency = CHF)),
+            Self::CLP => Ok(dirval!(PaymentCurrency = CLP)),
+            Self::CNY => Ok(dirval!(PaymentCurrency = CNY)),
+            Self::COP => Ok(dirval!(PaymentCurrency = COP)),
+            Self::CRC => Ok(dirval!(PaymentCurrency = CRC)),
+            Self::CUP => Ok(dirval!(PaymentCurrency = CUP)),
+            Self::CZK => Ok(dirval!(PaymentCurrency = CZK)),
+            Self::DJF => Ok(dirval!(PaymentCurrency = DJF)),
+            Self::DKK => Ok(dirval!(PaymentCurrency = DKK)),
+            Self::DOP => Ok(dirval!(PaymentCurrency = DOP)),
+            Self::DZD => Ok(dirval!(PaymentCurrency = DZD)),
+            Self::EGP => Ok(dirval!(PaymentCurrency = EGP)),
+            Self::ETB => Ok(dirval!(PaymentCurrency = ETB)),
+            Self::EUR => Ok(dirval!(PaymentCurrency = EUR)),
+            Self::FJD => Ok(dirval!(PaymentCurrency = FJD)),
+            Self::GBP => Ok(dirval!(PaymentCurrency = GBP)),
+            Self::GHS => Ok(dirval!(PaymentCurrency = GHS)),
+            Self::GIP => Ok(dirval!(PaymentCurrency = GIP)),
+            Self::GMD => Ok(dirval!(PaymentCurrency = GMD)),
+            Self::GNF => Ok(dirval!(PaymentCurrency = GNF)),
+            Self::GTQ => Ok(dirval!(PaymentCurrency = GTQ)),
+            Self::GYD => Ok(dirval!(PaymentCurrency = GYD)),
+            Self::HKD => Ok(dirval!(PaymentCurrency = HKD)),
+            Self::HNL => Ok(dirval!(PaymentCurrency = HNL)),
+            Self::HRK => Ok(dirval!(PaymentCurrency = HRK)),
+            Self::HTG => Ok(dirval!(PaymentCurrency = HTG)),
+            Self::HUF => Ok(dirval!(PaymentCurrency = HUF)),
+            Self::IDR => Ok(dirval!(PaymentCurrency = IDR)),
+            Self::ILS => Ok(dirval!(PaymentCurrency = ILS)),
+            Self::INR => Ok(dirval!(PaymentCurrency = INR)),
+            Self::JMD => Ok(dirval!(PaymentCurrency = JMD)),
+            Self::JOD => Ok(dirval!(PaymentCurrency = JOD)),
+            Self::JPY => Ok(dirval!(PaymentCurrency = JPY)),
+            Self::KES => Ok(dirval!(PaymentCurrency = KES)),
+            Self::KGS => Ok(dirval!(PaymentCurrency = KGS)),
+            Self::KHR => Ok(dirval!(PaymentCurrency = KHR)),
+            Self::KMF => Ok(dirval!(PaymentCurrency = KMF)),
+            Self::KRW => Ok(dirval!(PaymentCurrency = KRW)),
+            Self::KWD => Ok(dirval!(PaymentCurrency = KWD)),
+            Self::KYD => Ok(dirval!(PaymentCurrency = KYD)),
+            Self::KZT => Ok(dirval!(PaymentCurrency = KZT)),
+            Self::LAK => Ok(dirval!(PaymentCurrency = LAK)),
+            Self::LBP => Ok(dirval!(PaymentCurrency = LBP)),
+            Self::LKR => Ok(dirval!(PaymentCurrency = LKR)),
+            Self::LRD => Ok(dirval!(PaymentCurrency = LRD)),
+            Self::LSL => Ok(dirval!(PaymentCurrency = LSL)),
+            Self::MAD => Ok(dirval!(PaymentCurrency = MAD)),
+            Self::MDL => Ok(dirval!(PaymentCurrency = MDL)),
+            Self::MGA => Ok(dirval!(PaymentCurrency = MGA)),
+            Self::MKD => Ok(dirval!(PaymentCurrency = MKD)),
+            Self::MMK => Ok(dirval!(PaymentCurrency = MMK)),
+            Self::MNT => Ok(dirval!(PaymentCurrency = MNT)),
+            Self::MOP => Ok(dirval!(PaymentCurrency = MOP)),
+            Self::MUR => Ok(dirval!(PaymentCurrency = MUR)),
+            Self::MVR => Ok(dirval!(PaymentCurrency = MVR)),
+            Self::MWK => Ok(dirval!(PaymentCurrency = MWK)),
+            Self::MXN => Ok(dirval!(PaymentCurrency = MXN)),
+            Self::MYR => Ok(dirval!(PaymentCurrency = MYR)),
+            Self::NAD => Ok(dirval!(PaymentCurrency = NAD)),
+            Self::NGN => Ok(dirval!(PaymentCurrency = NGN)),
+            Self::NIO => Ok(dirval!(PaymentCurrency = NIO)),
+            Self::NOK => Ok(dirval!(PaymentCurrency = NOK)),
+            Self::NPR => Ok(dirval!(PaymentCurrency = NPR)),
+            Self::NZD => Ok(dirval!(PaymentCurrency = NZD)),
+            Self::OMR => Ok(dirval!(PaymentCurrency = OMR)),
+            Self::PEN => Ok(dirval!(PaymentCurrency = PEN)),
+            Self::PGK => Ok(dirval!(PaymentCurrency = PGK)),
+            Self::PHP => Ok(dirval!(PaymentCurrency = PHP)),
+            Self::PKR => Ok(dirval!(PaymentCurrency = PKR)),
+            Self::PLN => Ok(dirval!(PaymentCurrency = PLN)),
+            Self::PYG => Ok(dirval!(PaymentCurrency = PYG)),
+            Self::QAR => Ok(dirval!(PaymentCurrency = QAR)),
+            Self::RON => Ok(dirval!(PaymentCurrency = RON)),
+            Self::RUB => Ok(dirval!(PaymentCurrency = RUB)),
+            Self::RWF => Ok(dirval!(PaymentCurrency = RWF)),
+            Self::SAR => Ok(dirval!(PaymentCurrency = SAR)),
+            Self::SCR => Ok(dirval!(PaymentCurrency = SCR)),
+            Self::SEK => Ok(dirval!(PaymentCurrency = SEK)),
+            Self::SGD => Ok(dirval!(PaymentCurrency = SGD)),
+            Self::SLL => Ok(dirval!(PaymentCurrency = SLL)),
+            Self::SOS => Ok(dirval!(PaymentCurrency = SOS)),
+            Self::SSP => Ok(dirval!(PaymentCurrency = SSP)),
+            Self::SVC => Ok(dirval!(PaymentCurrency = SVC)),
+            Self::SZL => Ok(dirval!(PaymentCurrency = SZL)),
+            Self::THB => Ok(dirval!(PaymentCurrency = THB)),
+            Self::TRY => Ok(dirval!(PaymentCurrency = TRY)),
+            Self::TTD => Ok(dirval!(PaymentCurrency = TTD)),
+            Self::TWD => Ok(dirval!(PaymentCurrency = TWD)),
+            Self::TZS => Ok(dirval!(PaymentCurrency = TZS)),
+            Self::UGX => Ok(dirval!(PaymentCurrency = UGX)),
+            Self::USD => Ok(dirval!(PaymentCurrency = USD)),
+            Self::UYU => Ok(dirval!(PaymentCurrency = UYU)),
+            Self::UZS => Ok(dirval!(PaymentCurrency = UZS)),
+            Self::VND => Ok(dirval!(PaymentCurrency = VND)),
+            Self::VUV => Ok(dirval!(PaymentCurrency = VUV)),
+            Self::XAF => Ok(dirval!(PaymentCurrency = XAF)),
+            Self::XOF => Ok(dirval!(PaymentCurrency = XOF)),
+            Self::XPF => Ok(dirval!(PaymentCurrency = XPF)),
+            Self::YER => Ok(dirval!(PaymentCurrency = YER)),
+            Self::ZAR => Ok(dirval!(PaymentCurrency = ZAR)),
+        }
+    }
+}
+
+pub fn get_dir_country_dir_value(c: api_enums::Country) -> dir::enums::Country {
+    match c {
+        api_enums::Country::Afghanistan => dir::enums::Country::Afghanistan,
+        api_enums::Country::AlandIslands => dir::enums::Country::AlandIslands,
+        api_enums::Country::Albania => dir::enums::Country::Albania,
+        api_enums::Country::Algeria => dir::enums::Country::Algeria,
+        api_enums::Country::AmericanSamoa => dir::enums::Country::AmericanSamoa,
+        api_enums::Country::Andorra => dir::enums::Country::Andorra,
+        api_enums::Country::Angola => dir::enums::Country::Angola,
+        api_enums::Country::Anguilla => dir::enums::Country::Anguilla,
+        api_enums::Country::Antarctica => dir::enums::Country::Antarctica,
+        api_enums::Country::AntiguaAndBarbuda => dir::enums::Country::AntiguaAndBarbuda,
+        api_enums::Country::Argentina => dir::enums::Country::Argentina,
+        api_enums::Country::Armenia => dir::enums::Country::Armenia,
+        api_enums::Country::Aruba => dir::enums::Country::Aruba,
+        api_enums::Country::Australia => dir::enums::Country::Australia,
+        api_enums::Country::Austria => dir::enums::Country::Austria,
+        api_enums::Country::Azerbaijan => dir::enums::Country::Azerbaijan,
+        api_enums::Country::Bahamas => dir::enums::Country::Bahamas,
+        api_enums::Country::Bahrain => dir::enums::Country::Bahrain,
+        api_enums::Country::Bangladesh => dir::enums::Country::Bangladesh,
+        api_enums::Country::Barbados => dir::enums::Country::Barbados,
+        api_enums::Country::Belarus => dir::enums::Country::Belarus,
+        api_enums::Country::Belgium => dir::enums::Country::Belgium,
+        api_enums::Country::Belize => dir::enums::Country::Belize,
+        api_enums::Country::Benin => dir::enums::Country::Benin,
+        api_enums::Country::Bermuda => dir::enums::Country::Bermuda,
+        api_enums::Country::Bhutan => dir::enums::Country::Bhutan,
+        api_enums::Country::BoliviaPlurinationalState => {
+            dir::enums::Country::BoliviaPlurinationalState
+        }
+        api_enums::Country::BonaireSintEustatiusAndSaba => {
+            dir::enums::Country::BonaireSintEustatiusAndSaba
+        }
+        api_enums::Country::BosniaAndHerzegovina => dir::enums::Country::BosniaAndHerzegovina,
+        api_enums::Country::Botswana => dir::enums::Country::Botswana,
+        api_enums::Country::BouvetIsland => dir::enums::Country::BouvetIsland,
+        api_enums::Country::Brazil => dir::enums::Country::Brazil,
+        api_enums::Country::BritishIndianOceanTerritory => {
+            dir::enums::Country::BritishIndianOceanTerritory
+        }
+        api_enums::Country::BruneiDarussalam => dir::enums::Country::BruneiDarussalam,
+        api_enums::Country::Bulgaria => dir::enums::Country::Bulgaria,
+        api_enums::Country::BurkinaFaso => dir::enums::Country::BurkinaFaso,
+        api_enums::Country::Burundi => dir::enums::Country::Burundi,
+        api_enums::Country::CaboVerde => dir::enums::Country::CaboVerde,
+        api_enums::Country::Cambodia => dir::enums::Country::Cambodia,
+        api_enums::Country::Cameroon => dir::enums::Country::Cameroon,
+        api_enums::Country::Canada => dir::enums::Country::Canada,
+        api_enums::Country::CaymanIslands => dir::enums::Country::CaymanIslands,
+        api_enums::Country::CentralAfricanRepublic => dir::enums::Country::CentralAfricanRepublic,
+        api_enums::Country::Chad => dir::enums::Country::Chad,
+        api_enums::Country::Chile => dir::enums::Country::Chile,
+        api_enums::Country::China => dir::enums::Country::China,
+        api_enums::Country::ChristmasIsland => dir::enums::Country::ChristmasIsland,
+        api_enums::Country::CocosKeelingIslands => dir::enums::Country::CocosKeelingIslands,
+        api_enums::Country::Colombia => dir::enums::Country::Colombia,
+        api_enums::Country::Comoros => dir::enums::Country::Comoros,
+        api_enums::Country::Congo => dir::enums::Country::Congo,
+        api_enums::Country::CongoDemocraticRepublic => dir::enums::Country::CongoDemocraticRepublic,
+        api_enums::Country::CookIslands => dir::enums::Country::CookIslands,
+        api_enums::Country::CostaRica => dir::enums::Country::CostaRica,
+        api_enums::Country::CotedIvoire => dir::enums::Country::CotedIvoire,
+        api_enums::Country::Croatia => dir::enums::Country::Croatia,
+        api_enums::Country::Cuba => dir::enums::Country::Cuba,
+        api_enums::Country::Curacao => dir::enums::Country::Curacao,
+        api_enums::Country::Cyprus => dir::enums::Country::Cyprus,
+        api_enums::Country::Czechia => dir::enums::Country::Czechia,
+        api_enums::Country::Denmark => dir::enums::Country::Denmark,
+        api_enums::Country::Djibouti => dir::enums::Country::Djibouti,
+        api_enums::Country::Dominica => dir::enums::Country::Dominica,
+        api_enums::Country::DominicanRepublic => dir::enums::Country::DominicanRepublic,
+        api_enums::Country::Ecuador => dir::enums::Country::Ecuador,
+        api_enums::Country::Egypt => dir::enums::Country::Egypt,
+        api_enums::Country::ElSalvador => dir::enums::Country::ElSalvador,
+        api_enums::Country::EquatorialGuinea => dir::enums::Country::EquatorialGuinea,
+        api_enums::Country::Eritrea => dir::enums::Country::Eritrea,
+        api_enums::Country::Estonia => dir::enums::Country::Estonia,
+        api_enums::Country::Ethiopia => dir::enums::Country::Ethiopia,
+        api_enums::Country::FalklandIslandsMalvinas => dir::enums::Country::FalklandIslandsMalvinas,
+        api_enums::Country::FaroeIslands => dir::enums::Country::FaroeIslands,
+        api_enums::Country::Fiji => dir::enums::Country::Fiji,
+        api_enums::Country::Finland => dir::enums::Country::Finland,
+        api_enums::Country::France => dir::enums::Country::France,
+        api_enums::Country::FrenchGuiana => dir::enums::Country::FrenchGuiana,
+        api_enums::Country::FrenchPolynesia => dir::enums::Country::FrenchPolynesia,
+        api_enums::Country::FrenchSouthernTerritories => {
+            dir::enums::Country::FrenchSouthernTerritories
+        }
+        api_enums::Country::Gabon => dir::enums::Country::Gabon,
+        api_enums::Country::Gambia => dir::enums::Country::Gambia,
+        api_enums::Country::Georgia => dir::enums::Country::Georgia,
+        api_enums::Country::Germany => dir::enums::Country::Germany,
+        api_enums::Country::Ghana => dir::enums::Country::Ghana,
+        api_enums::Country::Gibraltar => dir::enums::Country::Gibraltar,
+        api_enums::Country::Greece => dir::enums::Country::Greece,
+        api_enums::Country::Greenland => dir::enums::Country::Greenland,
+        api_enums::Country::Grenada => dir::enums::Country::Grenada,
+        api_enums::Country::Guadeloupe => dir::enums::Country::Guadeloupe,
+        api_enums::Country::Guam => dir::enums::Country::Guam,
+        api_enums::Country::Guatemala => dir::enums::Country::Guatemala,
+        api_enums::Country::Guernsey => dir::enums::Country::Guernsey,
+        api_enums::Country::Guinea => dir::enums::Country::Guinea,
+        api_enums::Country::GuineaBissau => dir::enums::Country::GuineaBissau,
+        api_enums::Country::Guyana => dir::enums::Country::Guyana,
+        api_enums::Country::Haiti => dir::enums::Country::Haiti,
+        api_enums::Country::HeardIslandAndMcDonaldIslands => {
+            dir::enums::Country::HeardIslandAndMcDonaldIslands
+        }
+        api_enums::Country::HolySee => dir::enums::Country::HolySee,
+        api_enums::Country::Honduras => dir::enums::Country::Honduras,
+        api_enums::Country::HongKong => dir::enums::Country::HongKong,
+        api_enums::Country::Hungary => dir::enums::Country::Hungary,
+        api_enums::Country::Iceland => dir::enums::Country::Iceland,
+        api_enums::Country::India => dir::enums::Country::India,
+        api_enums::Country::Indonesia => dir::enums::Country::Indonesia,
+        api_enums::Country::IranIslamicRepublic => dir::enums::Country::IranIslamicRepublic,
+        api_enums::Country::Iraq => dir::enums::Country::Iraq,
+        api_enums::Country::Ireland => dir::enums::Country::Ireland,
+        api_enums::Country::IsleOfMan => dir::enums::Country::IsleOfMan,
+        api_enums::Country::Israel => dir::enums::Country::Israel,
+        api_enums::Country::Italy => dir::enums::Country::Italy,
+        api_enums::Country::Jamaica => dir::enums::Country::Jamaica,
+        api_enums::Country::Japan => dir::enums::Country::Japan,
+        api_enums::Country::Jersey => dir::enums::Country::Jersey,
+        api_enums::Country::Jordan => dir::enums::Country::Jordan,
+        api_enums::Country::Kazakhstan => dir::enums::Country::Kazakhstan,
+        api_enums::Country::Kenya => dir::enums::Country::Kenya,
+        api_enums::Country::Kiribati => dir::enums::Country::Kiribati,
+        api_enums::Country::KoreaDemocraticPeoplesRepublic => {
+            dir::enums::Country::KoreaDemocraticPeoplesRepublic
+        }
+        api_enums::Country::KoreaRepublic => dir::enums::Country::KoreaRepublic,
+        api_enums::Country::Kuwait => dir::enums::Country::Kuwait,
+        api_enums::Country::Kyrgyzstan => dir::enums::Country::Kyrgyzstan,
+        api_enums::Country::LaoPeoplesDemocraticRepublic => {
+            dir::enums::Country::LaoPeoplesDemocraticRepublic
+        }
+        api_enums::Country::Latvia => dir::enums::Country::Latvia,
+        api_enums::Country::Lebanon => dir::enums::Country::Lebanon,
+        api_enums::Country::Lesotho => dir::enums::Country::Lesotho,
+        api_enums::Country::Liberia => dir::enums::Country::Liberia,
+        api_enums::Country::Libya => dir::enums::Country::Libya,
+        api_enums::Country::Liechtenstein => dir::enums::Country::Liechtenstein,
+        api_enums::Country::Lithuania => dir::enums::Country::Lithuania,
+        api_enums::Country::Luxembourg => dir::enums::Country::Luxembourg,
+        api_enums::Country::Macao => dir::enums::Country::Macao,
+        api_enums::Country::MacedoniaTheFormerYugoslavRepublic => {
+            dir::enums::Country::MacedoniaTheFormerYugoslavRepublic
+        }
+        api_enums::Country::Madagascar => dir::enums::Country::Madagascar,
+        api_enums::Country::Malawi => dir::enums::Country::Malawi,
+        api_enums::Country::Malaysia => dir::enums::Country::Malaysia,
+        api_enums::Country::Maldives => dir::enums::Country::Maldives,
+        api_enums::Country::Mali => dir::enums::Country::Mali,
+        api_enums::Country::Malta => dir::enums::Country::Malta,
+        api_enums::Country::MarshallIslands => dir::enums::Country::MarshallIslands,
+        api_enums::Country::Martinique => dir::enums::Country::Martinique,
+        api_enums::Country::Mauritania => dir::enums::Country::Mauritania,
+        api_enums::Country::Mauritius => dir::enums::Country::Mauritius,
+        api_enums::Country::Mayotte => dir::enums::Country::Mayotte,
+        api_enums::Country::Mexico => dir::enums::Country::Mexico,
+        api_enums::Country::MicronesiaFederatedStates => {
+            dir::enums::Country::MicronesiaFederatedStates
+        }
+        api_enums::Country::MoldovaRepublic => dir::enums::Country::MoldovaRepublic,
+        api_enums::Country::Monaco => dir::enums::Country::Monaco,
+        api_enums::Country::Mongolia => dir::enums::Country::Mongolia,
+        api_enums::Country::Montenegro => dir::enums::Country::Montenegro,
+        api_enums::Country::Montserrat => dir::enums::Country::Montserrat,
+        api_enums::Country::Morocco => dir::enums::Country::Morocco,
+        api_enums::Country::Mozambique => dir::enums::Country::Mozambique,
+        api_enums::Country::Myanmar => dir::enums::Country::Myanmar,
+        api_enums::Country::Namibia => dir::enums::Country::Namibia,
+        api_enums::Country::Nauru => dir::enums::Country::Nauru,
+        api_enums::Country::Nepal => dir::enums::Country::Nepal,
+        api_enums::Country::Netherlands => dir::enums::Country::Netherlands,
+        api_enums::Country::NewCaledonia => dir::enums::Country::NewCaledonia,
+        api_enums::Country::NewZealand => dir::enums::Country::NewZealand,
+        api_enums::Country::Nicaragua => dir::enums::Country::Nicaragua,
+        api_enums::Country::Niger => dir::enums::Country::Niger,
+        api_enums::Country::Nigeria => dir::enums::Country::Nigeria,
+        api_enums::Country::Niue => dir::enums::Country::Niue,
+        api_enums::Country::NorfolkIsland => dir::enums::Country::NorfolkIsland,
+        api_enums::Country::NorthernMarianaIslands => dir::enums::Country::NorthernMarianaIslands,
+        api_enums::Country::Norway => dir::enums::Country::Norway,
+        api_enums::Country::Oman => dir::enums::Country::Oman,
+        api_enums::Country::Pakistan => dir::enums::Country::Pakistan,
+        api_enums::Country::Palau => dir::enums::Country::Palau,
+        api_enums::Country::PalestineState => dir::enums::Country::PalestineState,
+        api_enums::Country::Panama => dir::enums::Country::Panama,
+        api_enums::Country::PapuaNewGuinea => dir::enums::Country::PapuaNewGuinea,
+        api_enums::Country::Paraguay => dir::enums::Country::Paraguay,
+        api_enums::Country::Peru => dir::enums::Country::Peru,
+        api_enums::Country::Philippines => dir::enums::Country::Philippines,
+        api_enums::Country::Pitcairn => dir::enums::Country::Pitcairn,
+
+        api_enums::Country::Poland => dir::enums::Country::Poland,
+        api_enums::Country::Portugal => dir::enums::Country::Portugal,
+        api_enums::Country::PuertoRico => dir::enums::Country::PuertoRico,
+
+        api_enums::Country::Qatar => dir::enums::Country::Qatar,
+        api_enums::Country::Reunion => dir::enums::Country::Reunion,
+        api_enums::Country::Romania => dir::enums::Country::Romania,
+        api_enums::Country::RussianFederation => dir::enums::Country::RussianFederation,
+        api_enums::Country::Rwanda => dir::enums::Country::Rwanda,
+        api_enums::Country::SaintBarthelemy => dir::enums::Country::SaintBarthelemy,
+        api_enums::Country::SaintHelenaAscensionAndTristandaCunha => {
+            dir::enums::Country::SaintHelenaAscensionAndTristandaCunha
+        }
+        api_enums::Country::SaintKittsAndNevis => dir::enums::Country::SaintKittsAndNevis,
+        api_enums::Country::SaintLucia => dir::enums::Country::SaintLucia,
+        api_enums::Country::SaintMartinFrenchpart => dir::enums::Country::SaintMartinFrenchpart,
+        api_enums::Country::SaintPierreAndMiquelon => dir::enums::Country::SaintPierreAndMiquelon,
+        api_enums::Country::SaintVincentAndTheGrenadines => {
+            dir::enums::Country::SaintVincentAndTheGrenadines
+        }
+        api_enums::Country::Samoa => dir::enums::Country::Samoa,
+        api_enums::Country::SanMarino => dir::enums::Country::SanMarino,
+        api_enums::Country::SaoTomeAndPrincipe => dir::enums::Country::SaoTomeAndPrincipe,
+        api_enums::Country::SaudiArabia => dir::enums::Country::SaudiArabia,
+        api_enums::Country::Senegal => dir::enums::Country::Senegal,
+        api_enums::Country::Serbia => dir::enums::Country::Serbia,
+        api_enums::Country::Seychelles => dir::enums::Country::Seychelles,
+        api_enums::Country::SierraLeone => dir::enums::Country::SierraLeone,
+        api_enums::Country::Singapore => dir::enums::Country::Singapore,
+        api_enums::Country::SintMaartenDutchpart => dir::enums::Country::SintMaartenDutchpart,
+        api_enums::Country::Slovakia => dir::enums::Country::Slovakia,
+        api_enums::Country::Slovenia => dir::enums::Country::Slovenia,
+        api_enums::Country::SolomonIslands => dir::enums::Country::SolomonIslands,
+        api_enums::Country::Somalia => dir::enums::Country::Somalia,
+        api_enums::Country::SouthAfrica => dir::enums::Country::SouthAfrica,
+        api_enums::Country::SouthGeorgiaAndTheSouthSandwichIslands => {
+            dir::enums::Country::SouthGeorgiaAndTheSouthSandwichIslands
+        }
+        api_enums::Country::SouthSudan => dir::enums::Country::SouthSudan,
+        api_enums::Country::Spain => dir::enums::Country::Spain,
+        api_enums::Country::SriLanka => dir::enums::Country::SriLanka,
+        api_enums::Country::Sudan => dir::enums::Country::Sudan,
+        api_enums::Country::Suriname => dir::enums::Country::Suriname,
+        api_enums::Country::SvalbardAndJanMayen => dir::enums::Country::SvalbardAndJanMayen,
+        api_enums::Country::Swaziland => dir::enums::Country::Swaziland,
+        api_enums::Country::Sweden => dir::enums::Country::Sweden,
+        api_enums::Country::Switzerland => dir::enums::Country::Switzerland,
+        api_enums::Country::SyrianArabRepublic => dir::enums::Country::SyrianArabRepublic,
+        api_enums::Country::TaiwanProvinceOfChina => dir::enums::Country::TaiwanProvinceOfChina,
+        api_enums::Country::Tajikistan => dir::enums::Country::Tajikistan,
+        api_enums::Country::TanzaniaUnitedRepublic => dir::enums::Country::TanzaniaUnitedRepublic,
+        api_enums::Country::Thailand => dir::enums::Country::Thailand,
+        api_enums::Country::TimorLeste => dir::enums::Country::TimorLeste,
+        api_enums::Country::Togo => dir::enums::Country::Togo,
+        api_enums::Country::Tokelau => dir::enums::Country::Tokelau,
+        api_enums::Country::Tonga => dir::enums::Country::Tonga,
+        api_enums::Country::TrinidadAndTobago => dir::enums::Country::TrinidadAndTobago,
+        api_enums::Country::Tunisia => dir::enums::Country::Tunisia,
+        api_enums::Country::Turkey => dir::enums::Country::Turkey,
+        api_enums::Country::Turkmenistan => dir::enums::Country::Turkmenistan,
+        api_enums::Country::TurksAndCaicosIslands => dir::enums::Country::TurksAndCaicosIslands,
+        api_enums::Country::Tuvalu => dir::enums::Country::Tuvalu,
+        api_enums::Country::Uganda => dir::enums::Country::Uganda,
+        api_enums::Country::Ukraine => dir::enums::Country::Ukraine,
+        api_enums::Country::UnitedArabEmirates => dir::enums::Country::UnitedArabEmirates,
+        api_enums::Country::UnitedKingdomOfGreatBritainAndNorthernIreland => {
+            dir::enums::Country::UnitedKingdomOfGreatBritainAndNorthernIreland
+        }
+        api_enums::Country::UnitedStatesOfAmerica => dir::enums::Country::UnitedStatesOfAmerica,
+        api_enums::Country::UnitedStatesMinorOutlyingIslands => {
+            dir::enums::Country::UnitedStatesMinorOutlyingIslands
+        }
+        api_enums::Country::Uruguay => dir::enums::Country::Uruguay,
+        api_enums::Country::Uzbekistan => dir::enums::Country::Uzbekistan,
+        api_enums::Country::Vanuatu => dir::enums::Country::Vanuatu,
+        api_enums::Country::VenezuelaBolivarianRepublic => {
+            dir::enums::Country::VenezuelaBolivarianRepublic
+        }
+        api_enums::Country::Vietnam => dir::enums::Country::Vietnam,
+        api_enums::Country::VirginIslandsBritish => dir::enums::Country::VirginIslandsBritish,
+        api_enums::Country::VirginIslandsUS => dir::enums::Country::VirginIslandsUS,
+        api_enums::Country::WallisAndFutuna => dir::enums::Country::WallisAndFutuna,
+        api_enums::Country::WesternSahara => dir::enums::Country::WesternSahara,
+        api_enums::Country::Yemen => dir::enums::Country::Yemen,
+        api_enums::Country::Zambia => dir::enums::Country::Zambia,
+        api_enums::Country::Zimbabwe => dir::enums::Country::Zimbabwe,
+    }
+}
+
+pub fn business_country_to_dir_value(c: api_enums::Country) -> dir::DirValue {
+    dir::DirValue::BusinessCountry(get_dir_country_dir_value(c))
+}
+
+pub fn billing_country_to_dir_value(c: api_enums::Country) -> dir::DirValue {
+    dir::DirValue::BillingCountry(get_dir_country_dir_value(c))
+}
diff --git a/crates/masking/src/lib.rs b/crates/masking/src/lib.rs
index a0c4d3226a24..d092a1b5a8b6 100644
--- a/crates/masking/src/lib.rs
+++ b/crates/masking/src/lib.rs
@@ -42,7 +42,7 @@ mod vec;
 #[cfg(feature = "serde")]
 mod serde;
 #[cfg(feature = "serde")]
-pub use crate::serde::{Deserialize, SerializableSecret, Serialize};
+pub use crate::serde::{masked_serialize, Deserialize, SerializableSecret, Serialize};
 
 /// This module should be included with asterisk.
 ///
diff --git a/crates/masking/src/serde.rs b/crates/masking/src/serde.rs
index abdc117b6126..e57ed0301c2f 100644
--- a/crates/masking/src/serde.rs
+++ b/crates/masking/src/serde.rs
@@ -2,9 +2,10 @@
 //! Serde-related.
 //!
 
-pub use serde::{de, ser, Deserialize, Serialize};
+pub use serde::{de, ser, Deserialize, Serialize, Serializer};
+use serde_json::{value::Serializer as JsonValueSerializer, Value};
 
-use crate::{PeekInterface, Secret, Strategy, StrongSecret, ZeroizableSecret};
+use crate::{Secret, Strategy, StrongSecret, ZeroizableSecret};
 
 /// Marker trait for secret types which can be [`Serialize`]-d by [`serde`].
 ///
@@ -22,7 +23,7 @@ pub trait SerializableSecret: Serialize {}
 // #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
 // pub trait NonSerializableSecret: Serialize {}
 
-impl SerializableSecret for serde_json::Value {}
+impl SerializableSecret for Value {}
 impl SerializableSecret for u8 {}
 impl SerializableSecret for u16 {}
 
@@ -46,9 +47,9 @@ where
 {
     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     where
-        S: ser::Serializer,
+        S: Serializer,
     {
-        self.peek().serialize(serializer)
+        pii_serializer::pii_serialize(self, serializer)
     }
 }
 
@@ -72,8 +73,451 @@ where
 {
     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     where
-        S: serde::Serializer,
+        S: Serializer,
     {
-        self.peek().serialize(serializer)
+        pii_serializer::pii_serialize(self, serializer)
+    }
+}
+
+///
+/// Masked serialization.
+///
+/// the default behaviour for secrets is to serialize in exposed format since the common use cases
+/// for storing the secret to database or sending it over the network requires the secret to be exposed
+/// This method allows to serialize the secret in masked format if needed for logs or other insecure exposures
+pub fn masked_serialize<T: Serialize>(value: &T) -> Result<Value, serde_json::Error> {
+    value.serialize(PIISerializer {
+        inner: JsonValueSerializer,
+    })
+}
+
+use pii_serializer::PIISerializer;
+
+mod pii_serializer {
+    use std::fmt::Display;
+
+    pub(super) fn pii_serialize<
+        V: Serialize,
+        T: std::fmt::Debug + PeekInterface<V>,
+        S: Serializer,
+    >(
+        value: &T,
+        serializer: S,
+    ) -> Result<S::Ok, S::Error> {
+        // Mask the value if the serializer is of type PIISerializer
+        // or send empty map if the serializer is of type FlatMapSerializer over PiiSerializer
+        if std::any::type_name::<S>() == std::any::type_name::<PIISerializer>() {
+            format!("{value:?}").serialize(serializer)
+        } else if std::any::type_name::<S>()
+            == std::any::type_name::<
+                serde::__private::ser::FlatMapSerializer<'_, SerializeMap<PIISerializer>>,
+            >()
+        {
+            std::collections::HashMap::<String, String>::from([]).serialize(serializer)
+        } else {
+            value.peek().serialize(serializer)
+        }
+    }
+
+    use serde::{Serialize, Serializer};
+    use serde_json::{value::Serializer as JsonValueSerializer, Map, Value};
+
+    use crate::PeekInterface;
+
+    pub(super) struct PIISerializer {
+        pub inner: JsonValueSerializer,
+    }
+
+    impl Clone for PIISerializer {
+        fn clone(&self) -> Self {
+            Self {
+                inner: JsonValueSerializer,
+            }
+        }
+    }
+
+    impl Serializer for PIISerializer {
+        type Ok = Value;
+        type Error = serde_json::Error;
+
+        type SerializeSeq = SerializeVec<Self>;
+        type SerializeTuple = SerializeVec<Self>;
+        type SerializeTupleStruct = SerializeVec<Self>;
+        type SerializeTupleVariant = SerializeTupleVariant<Self>;
+        type SerializeMap = SerializeMap<Self>;
+        type SerializeStruct = SerializeMap<Self>;
+        type SerializeStructVariant = SerializeStructVariant<Self>;
+
+        #[inline]
+        fn serialize_bool(self, value: bool) -> Result<Self::Ok, Self::Error> {
+            self.inner.serialize_bool(value)
+        }
+
+        #[inline]
+        fn serialize_i8(self, value: i8) -> Result<Self::Ok, Self::Error> {
+            self.serialize_i64(value.into())
+        }
+
+        #[inline]
+        fn serialize_i16(self, value: i16) -> Result<Self::Ok, Self::Error> {
+            self.serialize_i64(value.into())
+        }
+
+        #[inline]
+        fn serialize_i32(self, value: i32) -> Result<Self::Ok, Self::Error> {
+            self.serialize_i64(value.into())
+        }
+
+        fn serialize_i64(self, value: i64) -> Result<Self::Ok, Self::Error> {
+            self.inner.serialize_i64(value)
+        }
+
+        fn serialize_i128(self, value: i128) -> Result<Self::Ok, Self::Error> {
+            self.inner.serialize_i128(value)
+        }
+
+        #[inline]
+        fn serialize_u8(self, value: u8) -> Result<Self::Ok, Self::Error> {
+            self.serialize_u64(value.into())
+        }
+
+        #[inline]
+        fn serialize_u16(self, value: u16) -> Result<Self::Ok, Self::Error> {
+            self.serialize_u64(value.into())
+        }
+
+        #[inline]
+        fn serialize_u32(self, value: u32) -> Result<Self::Ok, Self::Error> {
+            self.serialize_u64(value.into())
+        }
+
+        #[inline]
+        fn serialize_u64(self, value: u64) -> Result<Self::Ok, Self::Error> {
+            Ok(Value::Number(value.into()))
+        }
+
+        fn serialize_u128(self, value: u128) -> Result<Self::Ok, Self::Error> {
+            self.inner.serialize_u128(value)
+        }
+
+        #[inline]
+        fn serialize_f32(self, float: f32) -> Result<Self::Ok, Self::Error> {
+            Ok(Value::from(float))
+        }
+
+        #[inline]
+        fn serialize_f64(self, float: f64) -> Result<Self::Ok, Self::Error> {
+            Ok(Value::from(float))
+        }
+
+        #[inline]
+        fn serialize_char(self, value: char) -> Result<Self::Ok, Self::Error> {
+            let mut s = String::new();
+            s.push(value);
+            Ok(Value::String(s))
+        }
+
+        #[inline]
+        fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
+            Ok(Value::String(value.to_owned()))
+        }
+
+        fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok, Self::Error> {
+            let vec = value.iter().map(|&b| Value::Number(b.into())).collect();
+            Ok(Value::Array(vec))
+        }
+
+        #[inline]
+        fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+            Ok(Value::Null)
+        }
+
+        #[inline]
+        fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
+            self.serialize_unit()
+        }
+
+        #[inline]
+        fn serialize_unit_variant(
+            self,
+            _name: &'static str,
+            _variant_index: u32,
+            variant: &'static str,
+        ) -> Result<Self::Ok, Self::Error> {
+            self.serialize_str(variant)
+        }
+
+        #[inline]
+        fn serialize_newtype_struct<T>(
+            self,
+            _name: &'static str,
+            value: &T,
+        ) -> Result<Self::Ok, Self::Error>
+        where
+            T: ?Sized + Serialize,
+        {
+            value.serialize(self)
+        }
+
+        fn serialize_newtype_variant<T>(
+            self,
+            _name: &'static str,
+            _variant_index: u32,
+            variant: &'static str,
+            value: &T,
+        ) -> Result<Self::Ok, Self::Error>
+        where
+            T: ?Sized + Serialize,
+        {
+            let mut values = Map::new();
+            values.insert(String::from(variant), value.serialize(self)?);
+            Ok(Value::Object(values))
+        }
+
+        #[inline]
+        fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+            self.serialize_unit()
+        }
+
+        #[inline]
+        fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
+        where
+            T: ?Sized + Serialize,
+        {
+            value.serialize(self)
+        }
+
+        fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
+            Ok(SerializeVec {
+                vec: Vec::with_capacity(len.unwrap_or(0)),
+                ser: self,
+            })
+        }
+
+        fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
+            self.serialize_seq(Some(len))
+        }
+
+        fn serialize_tuple_struct(
+            self,
+            _name: &'static str,
+            len: usize,
+        ) -> Result<Self::SerializeTupleStruct, Self::Error> {
+            self.serialize_seq(Some(len))
+        }
+
+        fn serialize_tuple_variant(
+            self,
+            _name: &'static str,
+            _variant_index: u32,
+            variant: &'static str,
+            len: usize,
+        ) -> Result<Self::SerializeTupleVariant, Self::Error> {
+            Ok(SerializeTupleVariant {
+                name: String::from(variant),
+                vec: Vec::with_capacity(len),
+                ser: self,
+            })
+        }
+
+        fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
+            Ok(SerializeMap {
+                inner: self.clone().inner.serialize_map(len)?,
+                ser: self,
+            })
+        }
+
+        fn serialize_struct(
+            self,
+            _name: &'static str,
+            len: usize,
+        ) -> Result<Self::SerializeStruct, Self::Error> {
+            self.serialize_map(Some(len))
+        }
+
+        fn serialize_struct_variant(
+            self,
+            _name: &'static str,
+            _variant_index: u32,
+            variant: &'static str,
+            _len: usize,
+        ) -> Result<Self::SerializeStructVariant, Self::Error> {
+            Ok(SerializeStructVariant {
+                name: String::from(variant),
+                map: Map::new(),
+                ser: self,
+            })
+        }
+
+        fn collect_str<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
+        where
+            T: ?Sized + Display,
+        {
+            self.inner.collect_str(value)
+        }
+    }
+
+    pub(super) struct SerializeVec<T: Serializer> {
+        vec: Vec<Value>,
+        ser: T,
+    }
+
+    impl<T: Serializer<Ok = Value> + Clone> serde::ser::SerializeSeq for SerializeVec<T> {
+        type Ok = Value;
+        type Error = T::Error;
+
+        fn serialize_element<V>(&mut self, value: &V) -> Result<(), Self::Error>
+        where
+            V: ?Sized + Serialize,
+        {
+            self.vec.push(value.serialize(self.ser.clone())?);
+            Ok(())
+        }
+
+        fn end(self) -> Result<Self::Ok, Self::Error> {
+            Ok(Value::Array(self.vec))
+        }
+    }
+
+    impl<T: Serializer<Ok = Value> + Clone> serde::ser::SerializeTuple for SerializeVec<T> {
+        type Ok = Value;
+        type Error = T::Error;
+
+        fn serialize_element<V>(&mut self, value: &V) -> Result<(), Self::Error>
+        where
+            V: ?Sized + Serialize,
+        {
+            serde::ser::SerializeSeq::serialize_element(self, value)
+        }
+
+        fn end(self) -> Result<Self::Ok, Self::Error> {
+            serde::ser::SerializeSeq::end(self)
+        }
+    }
+
+    impl<T: Serializer<Ok = Value> + Clone> serde::ser::SerializeTupleStruct for SerializeVec<T> {
+        type Ok = Value;
+        type Error = T::Error;
+
+        fn serialize_field<V>(&mut self, value: &V) -> Result<(), Self::Error>
+        where
+            V: ?Sized + Serialize,
+        {
+            serde::ser::SerializeSeq::serialize_element(self, value)
+        }
+
+        fn end(self) -> Result<Self::Ok, Self::Error> {
+            serde::ser::SerializeSeq::end(self)
+        }
+    }
+
+    pub(super) struct SerializeStructVariant<T: Serializer> {
+        name: String,
+        map: Map<String, Value>,
+        ser: T,
+    }
+
+    impl<T: Serializer<Ok = Value> + Clone> serde::ser::SerializeStructVariant
+        for SerializeStructVariant<T>
+    {
+        type Ok = Value;
+        type Error = T::Error;
+
+        fn serialize_field<V>(&mut self, key: &'static str, value: &V) -> Result<(), Self::Error>
+        where
+            V: ?Sized + Serialize,
+        {
+            self.map
+                .insert(String::from(key), value.serialize(self.ser.clone())?);
+            Ok(())
+        }
+
+        fn end(self) -> Result<Self::Ok, Self::Error> {
+            let mut object = Map::new();
+
+            object.insert(self.name, Value::Object(self.map));
+
+            Ok(Value::Object(object))
+        }
+    }
+
+    pub(super) struct SerializeTupleVariant<T: Serializer> {
+        name: String,
+        vec: Vec<Value>,
+        ser: T,
+    }
+
+    impl<T: Serializer<Ok = Value> + Clone> serde::ser::SerializeTupleVariant
+        for SerializeTupleVariant<T>
+    {
+        type Ok = Value;
+        type Error = T::Error;
+
+        fn serialize_field<V>(&mut self, value: &V) -> Result<(), Self::Error>
+        where
+            V: ?Sized + Serialize,
+        {
+            self.vec.push(value.serialize(self.ser.clone())?);
+            Ok(())
+        }
+
+        fn end(self) -> Result<Value, Self::Error> {
+            let mut object = Map::new();
+
+            object.insert(self.name, Value::Array(self.vec));
+
+            Ok(Value::Object(object))
+        }
+    }
+
+    pub(super) struct SerializeMap<T: Serializer> {
+        inner: <serde_json::value::Serializer as Serializer>::SerializeMap,
+        ser: T,
+    }
+
+    impl<T: Serializer<Ok = Value, Error = serde_json::Error> + Clone> serde::ser::SerializeMap
+        for SerializeMap<T>
+    {
+        type Ok = Value;
+        type Error = T::Error;
+
+        fn serialize_key<V>(&mut self, key: &V) -> Result<(), Self::Error>
+        where
+            V: ?Sized + Serialize,
+        {
+            self.inner.serialize_key(key)?;
+            Ok(())
+        }
+
+        fn serialize_value<V>(&mut self, value: &V) -> Result<(), Self::Error>
+        where
+            V: ?Sized + Serialize,
+        {
+            let value = value.serialize(self.ser.clone())?;
+            self.inner.serialize_value(&value)?;
+            Ok(())
+        }
+
+        fn end(self) -> Result<Value, Self::Error> {
+            self.inner.end()
+        }
+    }
+
+    impl<T: Serializer<Ok = Value, Error = serde_json::Error> + Clone> serde::ser::SerializeStruct
+        for SerializeMap<T>
+    {
+        type Ok = Value;
+        type Error = T::Error;
+
+        fn serialize_field<V>(&mut self, key: &'static str, value: &V) -> Result<(), Self::Error>
+        where
+            V: ?Sized + Serialize,
+        {
+            serde::ser::SerializeMap::serialize_entry(self, key, value)
+        }
+
+        fn end(self) -> Result<Value, Self::Error> {
+            serde::ser::SerializeMap::end(self)
+        }
     }
 }
diff --git a/crates/redis_interface/Cargo.toml b/crates/redis_interface/Cargo.toml
index 8066787dcae2..9d3ae724d432 100644
--- a/crates/redis_interface/Cargo.toml
+++ b/crates/redis_interface/Cargo.toml
@@ -9,7 +9,7 @@ license.workspace = true
 
 [dependencies]
 error-stack = "0.3.1"
-fred = { version = "6.3.0", features = ["metrics", "partial-tracing","subscriber-client"] }
+fred = { version = "6.3.0", features = ["metrics", "partial-tracing", "subscriber-client"] }
 futures = "0.3"
 serde = { version = "1.0.163", features = ["derive"] }
 thiserror = "1.0.40"
diff --git a/crates/redis_interface/src/commands.rs b/crates/redis_interface/src/commands.rs
index d53fd1625fe4..ca85d19d38b0 100644
--- a/crates/redis_interface/src/commands.rs
+++ b/crates/redis_interface/src/commands.rs
@@ -248,7 +248,7 @@ impl super::RedisConnectionPool {
         &self,
         key: &str,
         values: V,
-        ttl: Option<u32>,
+        ttl: Option<i64>,
     ) -> CustomResult<(), errors::RedisError>
     where
         V: TryInto<RedisMap> + Debug + Send + Sync,
@@ -260,11 +260,10 @@ impl super::RedisConnectionPool {
             .await
             .into_report()
             .change_context(errors::RedisError::SetHashFailed);
-
         // setting expiry for the key
         output
             .async_and_then(|_| {
-                self.set_expiry(key, ttl.unwrap_or(self.config.default_hash_ttl).into())
+                self.set_expiry(key, ttl.unwrap_or(self.config.default_hash_ttl.into()))
             })
             .await
     }
diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml
index 8cbded8f5368..01595dc18cd5 100644
--- a/crates/router/Cargo.toml
+++ b/crates/router/Cargo.toml
@@ -9,42 +9,48 @@ readme = "README.md"
 license.workspace = true
 
 [features]
-default = ["kv_store", "stripe", "oltp", "olap", "accounts_cache", "dummy_connector", "payouts"]
+default = ["kv_store", "stripe", "oltp", "olap", "backwards_compatibility", "accounts_cache", "dummy_connector", "payouts", "profile_specific_fallback_routing", "retry"]
 s3 = ["dep:aws-sdk-s3", "dep:aws-config"]
 kms = ["external_services/kms", "dep:aws-config"]
 email = ["external_services/email", "dep:aws-config"]
+basilisk = ["kms"]
 stripe = ["dep:serde_qs"]
-release = ["kms", "stripe", "s3", "email","accounts_cache"]
+release = ["kms", "stripe", "basilisk", "s3", "email", "business_profile_routing", "accounts_cache", "kv_store", "profile_specific_fallback_routing"]
 olap = ["data_models/olap", "storage_impl/olap", "scheduler/olap"]
-oltp = ["data_models/oltp", "storage_impl/oltp"]
+oltp = ["storage_impl/oltp"]
 kv_store = ["scheduler/kv_store"]
 accounts_cache = []
 openapi = ["olap", "oltp", "payouts"]
 vergen = ["router_env/vergen"]
-dummy_connector = ["api_models/dummy_connector"]
+backwards_compatibility = ["api_models/backwards_compatibility"]
+business_profile_routing = ["api_models/business_profile_routing"]
+profile_specific_fallback_routing = []
+dummy_connector = ["api_models/dummy_connector", "euclid/dummy_connector", "kgraph_utils/dummy_connector"]
+connector_choice_mca_id = ["api_models/connector_choice_mca_id", "euclid/connector_choice_mca_id", "kgraph_utils/connector_choice_mca_id"]
 external_access_dc = ["dummy_connector"]
 detailed_errors = ["api_models/detailed_errors", "error-stack/serde"]
 payouts = []
-api_locking = []
-
+retry = []
 
 [dependencies]
-actix = "0.13.0"
 actix-cors = "0.6.4"
 actix-multipart = "0.6.0"
 actix-rt = "2.8.0"
 actix-web = "4.3.1"
-async-bb8-diesel = "0.1.0"
+async-bb8-diesel = { git = "https://github.com/jarnura/async-bb8-diesel", rev = "53b4ab901aab7635c8215fd1c2d542c8db443094" }
+argon2 = { version = "0.5.0", features = ["std"] }
 async-trait = "0.1.68"
 aws-config = { version = "0.55.3", optional = true }
 aws-sdk-s3 = { version = "0.28.0", optional = true }
 base64 = "0.21.2"
 bb8 = "0.8"
+bigdecimal = "0.3.1"
 blake3 = "1.3.3"
 bytes = "1.4.0"
 clap = { version = "4.3.2", default-features = false, features = ["std", "derive", "help", "usage"] }
 config = { version = "0.13.3", features = ["toml"] }
 diesel = { version = "2.1.0", features = ["postgres"] }
+digest = "0.9"
 dyn-clone = "1.0.11"
 encoding_rs = "0.8.32"
 error-stack = "0.3.1"
@@ -56,57 +62,60 @@ image = "0.23.14"
 infer = "0.13.0"
 josekit = "0.8.3"
 jsonwebtoken = "8.3.0"
-literally = "0.1.3"
 maud = { version = "0.25", features = ["actix-web"] }
 mimalloc = { version = "0.1", optional = true }
 mime = "0.3.17"
 nanoid = "0.4.0"
 num_cpus = "1.15.0"
 once_cell = "1.18.0"
+openssl = "0.10.55"
 qrcode = "0.12.0"
 rand = "0.8.5"
+rand_chacha = "0.3.1"
 regex = "1.8.4"
 reqwest = { version = "0.11.18", features = ["json", "native-tls", "gzip", "multipart"] }
 ring = "0.16.20"
 roxmltree = "0.18.0"
+rustc-hash = "1.1.0"
 serde = { version = "1.0.163", features = ["derive"] }
 serde_json = "1.0.96"
 serde_path_to_error = "0.1.11"
 serde_qs = { version = "0.12.0", optional = true }
 serde_urlencoded = "0.7.1"
 serde_with = "3.0.0"
-signal-hook = "0.3.15"
+sha-1 = { version = "0.9" }
+sqlx = { version = "0.6.3", features = ["postgres", "runtime-actix", "runtime-actix-native-tls", "time", "bigdecimal"] }
 strum = { version = "0.24.1", features = ["derive"] }
+tera = "1.19.1"
 thiserror = "1.0.40"
 time = { version = "0.3.21", features = ["serde", "serde-well-known", "std"] }
 tokio = { version = "1.28.2", features = ["macros", "rt-multi-thread"] }
-tera = "1.19.1"
+unicode-segmentation = "1.10.1"
 url = { version = "2.4.0", features = ["serde"] }
 utoipa = { version = "3.3.0", features = ["preserve_order", "time"] }
 utoipa-swagger-ui = { version = "3.1.3", features = ["actix-web"] }
 uuid = { version = "1.3.3", features = ["serde", "v4"] }
-openssl = "0.10.55"
+validator = "0.16.0"
 x509-parser = "0.15.0"
-sha-1 = { version = "0.9"}
-digest = "0.9"
+tracing-futures = { version = "0.2.5", features = ["tokio"] }
 
 # First party crates
 api_models = { version = "0.1.0", path = "../api_models", features = ["errors"] }
 cards = { version = "0.1.0", path = "../cards" }
+common_enums = { version = "0.1.0", path = "../common_enums" }
 common_utils = { version = "0.1.0", path = "../common_utils", features = ["signals", "async_ext", "logs"] }
+data_models = { version = "0.1.0", path = "../data_models", default-features = false }
+diesel_models = { version = "0.1.0", path = "../diesel_models", features = ["kv_store"] }
+euclid = { version = "0.1.0", path = "../euclid", features = ["valued_jit"] }
 external_services = { version = "0.1.0", path = "../external_services" }
+kgraph_utils = { version = "0.1.0", path = "../kgraph_utils" }
 masking = { version = "0.1.0", path = "../masking" }
 redis_interface = { version = "0.1.0", path = "../redis_interface" }
 router_derive = { version = "0.1.0", path = "../router_derive" }
 router_env = { version = "0.1.0", path = "../router_env", features = ["log_extra_implicit_fields", "log_custom_entries_to_extra"] }
-diesel_models = { version = "0.1.0", path = "../diesel_models", features = ["kv_store"] }
-scheduler = { version = "0.1.0", path = "../scheduler", default-features = false}
-data_models = { version = "0.1.0", path = "../data_models", default-features = false }
+scheduler = { version = "0.1.0", path = "../scheduler", default-features = false }
 storage_impl = { version = "0.1.0", path = "../storage_impl", default-features = false }
 
-[target.'cfg(not(target_os = "windows"))'.dependencies]
-signal-hook-tokio = { version = "0.3.1", features = ["futures-v0_3"] }
-
 [build-dependencies]
 router_env = { version = "0.1.0", path = "../router_env", default-features = false }
 
@@ -116,10 +125,8 @@ awc = { version = "3.1.1", features = ["rustls"] }
 derive_deref = "1.1.1"
 rand = "0.8.5"
 serial_test = "2.0.0"
-thirtyfour = "0.31.0"
 time = { version = "0.3.21", features = ["macros"] }
 tokio = "1.28.2"
-toml = "0.7.4"
 wiremock = "0.5"
 
 # First party dev-dependencies
diff --git a/crates/router/src/analytics.rs b/crates/router/src/analytics.rs
new file mode 100644
index 000000000000..d57403d92989
--- /dev/null
+++ b/crates/router/src/analytics.rs
@@ -0,0 +1,129 @@
+mod core;
+mod errors;
+pub mod metrics;
+mod payments;
+mod query;
+mod refunds;
+pub mod routes;
+
+mod sqlx;
+mod types;
+mod utils;
+
+use api_models::analytics::{
+    payments::{PaymentDimensions, PaymentFilters, PaymentMetrics, PaymentMetricsBucketIdentifier},
+    refunds::{RefundDimensions, RefundFilters, RefundMetrics, RefundMetricsBucketIdentifier},
+    Granularity, TimeRange,
+};
+use router_env::{instrument, tracing};
+
+use self::{
+    payments::metrics::{PaymentMetric, PaymentMetricRow},
+    refunds::metrics::{RefundMetric, RefundMetricRow},
+    sqlx::SqlxClient,
+};
+use crate::configs::settings::Database;
+
+#[derive(Clone, Debug)]
+pub enum AnalyticsProvider {
+    Sqlx(SqlxClient),
+}
+
+impl Default for AnalyticsProvider {
+    fn default() -> Self {
+        Self::Sqlx(SqlxClient::default())
+    }
+}
+
+impl AnalyticsProvider {
+    #[instrument(skip_all)]
+    pub async fn get_payment_metrics(
+        &self,
+        metric: &PaymentMetrics,
+        dimensions: &[PaymentDimensions],
+        merchant_id: &str,
+        filters: &PaymentFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+    ) -> types::MetricsResult<Vec<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>> {
+        // Metrics to get the fetch time for each payment metric
+        metrics::request::record_operation_time(
+            async {
+                match self {
+                    Self::Sqlx(pool) => {
+                        metric
+                            .load_metrics(
+                                dimensions,
+                                merchant_id,
+                                filters,
+                                granularity,
+                                time_range,
+                                pool,
+                            )
+                            .await
+                    }
+                }
+            },
+            &metrics::METRIC_FETCH_TIME,
+            metric,
+            self,
+        )
+        .await
+    }
+
+    pub async fn get_refund_metrics(
+        &self,
+        metric: &RefundMetrics,
+        dimensions: &[RefundDimensions],
+        merchant_id: &str,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+    ) -> types::MetricsResult<Vec<(RefundMetricsBucketIdentifier, RefundMetricRow)>> {
+        match self {
+            Self::Sqlx(pool) => {
+                metric
+                    .load_metrics(
+                        dimensions,
+                        merchant_id,
+                        filters,
+                        granularity,
+                        time_range,
+                        pool,
+                    )
+                    .await
+            }
+        }
+    }
+
+    pub async fn from_conf(
+        config: &AnalyticsConfig,
+        #[cfg(feature = "kms")] kms_client: &external_services::kms::KmsClient,
+    ) -> Self {
+        match config {
+            AnalyticsConfig::Sqlx { sqlx } => Self::Sqlx(
+                SqlxClient::from_conf(
+                    sqlx,
+                    #[cfg(feature = "kms")]
+                    kms_client,
+                )
+                .await,
+            ),
+        }
+    }
+}
+
+#[derive(Clone, Debug, serde::Deserialize)]
+#[serde(tag = "source")]
+#[serde(rename_all = "lowercase")]
+pub enum AnalyticsConfig {
+    Sqlx { sqlx: Database },
+}
+
+impl Default for AnalyticsConfig {
+    fn default() -> Self {
+        Self::Sqlx {
+            sqlx: Database::default(),
+        }
+    }
+}
diff --git a/crates/router/src/analytics/core.rs b/crates/router/src/analytics/core.rs
new file mode 100644
index 000000000000..bf124a6c0e85
--- /dev/null
+++ b/crates/router/src/analytics/core.rs
@@ -0,0 +1,96 @@
+use api_models::analytics::{
+    payments::PaymentDimensions, refunds::RefundDimensions, FilterValue, GetInfoResponse,
+    GetPaymentFiltersRequest, GetRefundFilterRequest, PaymentFiltersResponse, RefundFilterValue,
+    RefundFiltersResponse,
+};
+use error_stack::ResultExt;
+
+use super::{
+    errors::{self, AnalyticsError},
+    payments::filters::{get_payment_filter_for_dimension, FilterRow},
+    refunds::filters::{get_refund_filter_for_dimension, RefundFilterRow},
+    types::AnalyticsDomain,
+    utils, AnalyticsProvider,
+};
+use crate::{services::ApplicationResponse, types::domain};
+
+pub type AnalyticsApiResponse<T> = errors::AnalyticsResult<ApplicationResponse<T>>;
+
+pub async fn get_domain_info(domain: AnalyticsDomain) -> AnalyticsApiResponse<GetInfoResponse> {
+    let info = match domain {
+        AnalyticsDomain::Payments => GetInfoResponse {
+            metrics: utils::get_payment_metrics_info(),
+            download_dimensions: None,
+            dimensions: utils::get_payment_dimensions(),
+        },
+        AnalyticsDomain::Refunds => GetInfoResponse {
+            metrics: utils::get_refund_metrics_info(),
+            download_dimensions: None,
+            dimensions: utils::get_refund_dimensions(),
+        },
+    };
+    Ok(ApplicationResponse::Json(info))
+}
+
+pub async fn payment_filters_core(
+    pool: AnalyticsProvider,
+    req: GetPaymentFiltersRequest,
+    merchant: domain::MerchantAccount,
+) -> AnalyticsApiResponse<PaymentFiltersResponse> {
+    let mut res = PaymentFiltersResponse::default();
+
+    for dim in req.group_by_names {
+        let values = match pool.clone() {
+            AnalyticsProvider::Sqlx(pool) => {
+                get_payment_filter_for_dimension(dim, &merchant.merchant_id, &req.time_range, &pool)
+                    .await
+            }
+        }
+        .change_context(AnalyticsError::UnknownError)?
+        .into_iter()
+        .filter_map(|fil: FilterRow| match dim {
+            PaymentDimensions::Currency => fil.currency.map(|i| i.as_ref().to_string()),
+            PaymentDimensions::PaymentStatus => fil.status.map(|i| i.as_ref().to_string()),
+            PaymentDimensions::Connector => fil.connector,
+            PaymentDimensions::AuthType => fil.authentication_type.map(|i| i.as_ref().to_string()),
+            PaymentDimensions::PaymentMethod => fil.payment_method,
+        })
+        .collect::<Vec<String>>();
+        res.query_data.push(FilterValue {
+            dimension: dim,
+            values,
+        })
+    }
+
+    Ok(ApplicationResponse::Json(res))
+}
+
+pub async fn refund_filter_core(
+    pool: AnalyticsProvider,
+    req: GetRefundFilterRequest,
+    merchant: domain::MerchantAccount,
+) -> AnalyticsApiResponse<RefundFiltersResponse> {
+    let mut res = RefundFiltersResponse::default();
+    for dim in req.group_by_names {
+        let values = match pool.clone() {
+            AnalyticsProvider::Sqlx(pool) => {
+                get_refund_filter_for_dimension(dim, &merchant.merchant_id, &req.time_range, &pool)
+                    .await
+            }
+        }
+        .change_context(AnalyticsError::UnknownError)?
+        .into_iter()
+        .filter_map(|fil: RefundFilterRow| match dim {
+            RefundDimensions::Currency => fil.currency.map(|i| i.as_ref().to_string()),
+            RefundDimensions::RefundStatus => fil.refund_status.map(|i| i.as_ref().to_string()),
+            RefundDimensions::Connector => fil.connector,
+            RefundDimensions::RefundType => fil.refund_type.map(|i| i.as_ref().to_string()),
+        })
+        .collect::<Vec<String>>();
+        res.query_data.push(RefundFilterValue {
+            dimension: dim,
+            values,
+        })
+    }
+    Ok(ApplicationResponse::Json(res))
+}
diff --git a/crates/router/src/analytics/errors.rs b/crates/router/src/analytics/errors.rs
new file mode 100644
index 000000000000..da0b2f239cd7
--- /dev/null
+++ b/crates/router/src/analytics/errors.rs
@@ -0,0 +1,32 @@
+use api_models::errors::types::{ApiError, ApiErrorResponse};
+use common_utils::errors::{CustomResult, ErrorSwitch};
+
+pub type AnalyticsResult<T> = CustomResult<T, AnalyticsError>;
+
+#[derive(Debug, Clone, serde::Serialize, thiserror::Error)]
+pub enum AnalyticsError {
+    #[allow(dead_code)]
+    #[error("Not implemented: {0}")]
+    NotImplemented(&'static str),
+    #[error("Unknown Analytics Error")]
+    UnknownError,
+}
+
+impl ErrorSwitch<ApiErrorResponse> for AnalyticsError {
+    fn switch(&self) -> ApiErrorResponse {
+        match self {
+            Self::NotImplemented(feature) => ApiErrorResponse::NotImplemented(ApiError::new(
+                "IR",
+                0,
+                format!("{feature} is not implemented."),
+                None,
+            )),
+            Self::UnknownError => ApiErrorResponse::InternalServerError(ApiError::new(
+                "HE",
+                0,
+                "Something went wrong",
+                None,
+            )),
+        }
+    }
+}
diff --git a/crates/router/src/analytics/metrics.rs b/crates/router/src/analytics/metrics.rs
new file mode 100644
index 000000000000..6222315a8c06
--- /dev/null
+++ b/crates/router/src/analytics/metrics.rs
@@ -0,0 +1,9 @@
+use router_env::{global_meter, histogram_metric, histogram_metric_u64, metrics_context};
+
+metrics_context!(CONTEXT);
+global_meter!(GLOBAL_METER, "ROUTER_API");
+
+histogram_metric!(METRIC_FETCH_TIME, GLOBAL_METER);
+histogram_metric_u64!(BUCKETS_FETCHED, GLOBAL_METER);
+
+pub mod request;
diff --git a/crates/router/src/analytics/metrics/request.rs b/crates/router/src/analytics/metrics/request.rs
new file mode 100644
index 000000000000..b7c202f2db25
--- /dev/null
+++ b/crates/router/src/analytics/metrics/request.rs
@@ -0,0 +1,60 @@
+pub fn add_attributes<T: Into<router_env::opentelemetry::Value>>(
+    key: &'static str,
+    value: T,
+) -> router_env::opentelemetry::KeyValue {
+    router_env::opentelemetry::KeyValue::new(key, value)
+}
+
+#[inline]
+pub async fn record_operation_time<F, R>(
+    future: F,
+    metric: &once_cell::sync::Lazy<router_env::opentelemetry::metrics::Histogram<f64>>,
+    metric_name: &api_models::analytics::payments::PaymentMetrics,
+    source: &crate::analytics::AnalyticsProvider,
+) -> R
+where
+    F: futures::Future<Output = R>,
+{
+    let (result, time) = time_future(future).await;
+    let attributes = &[
+        add_attributes("metric_name", metric_name.to_string()),
+        add_attributes(
+            "source",
+            match source {
+                crate::analytics::AnalyticsProvider::Sqlx(_) => "Sqlx",
+            },
+        ),
+    ];
+    let value = time.as_secs_f64();
+    metric.record(&super::CONTEXT, value, attributes);
+
+    router_env::logger::debug!("Attributes: {:?}, Time: {}", attributes, value);
+    result
+}
+
+use std::time;
+
+#[inline]
+pub async fn time_future<F, R>(future: F) -> (R, time::Duration)
+where
+    F: futures::Future<Output = R>,
+{
+    let start = time::Instant::now();
+    let result = future.await;
+    let time_spent = start.elapsed();
+    (result, time_spent)
+}
+
+#[macro_export]
+macro_rules! histogram_metric {
+    ($name:ident, $meter:ident) => {
+        pub(crate) static $name: once_cell::sync::Lazy<
+            $crate::opentelemetry::metrics::Histogram<u64>,
+        > = once_cell::sync::Lazy::new(|| $meter.u64_histogram(stringify!($name)).init());
+    };
+    ($name:ident, $meter:ident, $description:literal) => {
+        pub(crate) static $name: once_cell::sync::Lazy<
+            $crate::opentelemetry::metrics::Histogram<u64>,
+        > = once_cell::sync::Lazy::new(|| $meter.u64_histogram($description).init());
+    };
+}
diff --git a/crates/router/src/analytics/payments.rs b/crates/router/src/analytics/payments.rs
new file mode 100644
index 000000000000..527bf75a3c72
--- /dev/null
+++ b/crates/router/src/analytics/payments.rs
@@ -0,0 +1,13 @@
+pub mod accumulator;
+mod core;
+pub mod filters;
+pub mod metrics;
+pub mod types;
+pub use accumulator::{PaymentMetricAccumulator, PaymentMetricsAccumulator};
+
+pub trait PaymentAnalytics:
+    metrics::PaymentMetricAnalytics + filters::PaymentFilterAnalytics
+{
+}
+
+pub use self::core::get_metrics;
diff --git a/crates/router/src/analytics/payments/accumulator.rs b/crates/router/src/analytics/payments/accumulator.rs
new file mode 100644
index 000000000000..5eebd0974693
--- /dev/null
+++ b/crates/router/src/analytics/payments/accumulator.rs
@@ -0,0 +1,150 @@
+use api_models::analytics::payments::PaymentMetricsBucketValue;
+use common_enums::enums as storage_enums;
+use router_env::logger;
+
+use super::metrics::PaymentMetricRow;
+
+#[derive(Debug, Default)]
+pub struct PaymentMetricsAccumulator {
+    pub payment_success_rate: SuccessRateAccumulator,
+    pub payment_count: CountAccumulator,
+    pub payment_success: CountAccumulator,
+    pub processed_amount: SumAccumulator,
+    pub avg_ticket_size: AverageAccumulator,
+}
+
+#[derive(Debug, Default)]
+pub struct SuccessRateAccumulator {
+    pub success: i64,
+    pub total: i64,
+}
+
+#[derive(Debug, Default)]
+#[repr(transparent)]
+pub struct CountAccumulator {
+    pub count: Option<i64>,
+}
+
+#[derive(Debug, Default)]
+#[repr(transparent)]
+pub struct SumAccumulator {
+    pub total: Option<i64>,
+}
+
+#[derive(Debug, Default)]
+pub struct AverageAccumulator {
+    pub total: u32,
+    pub count: u32,
+}
+
+pub trait PaymentMetricAccumulator {
+    type MetricOutput;
+
+    fn add_metrics_bucket(&mut self, metrics: &PaymentMetricRow);
+
+    fn collect(self) -> Self::MetricOutput;
+}
+
+impl PaymentMetricAccumulator for SuccessRateAccumulator {
+    type MetricOutput = Option<f64>;
+
+    fn add_metrics_bucket(&mut self, metrics: &PaymentMetricRow) {
+        if let Some(ref status) = metrics.status {
+            if status.as_ref() == &storage_enums::AttemptStatus::Charged {
+                self.success += metrics.count.unwrap_or_default();
+            }
+        };
+        self.total += metrics.count.unwrap_or_default();
+    }
+
+    fn collect(self) -> Self::MetricOutput {
+        if self.total <= 0 {
+            None
+        } else {
+            Some(
+                f64::from(u32::try_from(self.success).ok()?) * 100.0
+                    / f64::from(u32::try_from(self.total).ok()?),
+            )
+        }
+    }
+}
+
+impl PaymentMetricAccumulator for CountAccumulator {
+    type MetricOutput = Option<u64>;
+    #[inline]
+    fn add_metrics_bucket(&mut self, metrics: &PaymentMetricRow) {
+        self.count = match (self.count, metrics.count) {
+            (None, None) => None,
+            (None, i @ Some(_)) | (i @ Some(_), None) => i,
+            (Some(a), Some(b)) => Some(a + b),
+        }
+    }
+    #[inline]
+    fn collect(self) -> Self::MetricOutput {
+        self.count.and_then(|i| u64::try_from(i).ok())
+    }
+}
+
+impl PaymentMetricAccumulator for SumAccumulator {
+    type MetricOutput = Option<u64>;
+    #[inline]
+    fn add_metrics_bucket(&mut self, metrics: &PaymentMetricRow) {
+        self.total = match (
+            self.total,
+            metrics
+                .total
+                .as_ref()
+                .and_then(bigdecimal::ToPrimitive::to_i64),
+        ) {
+            (None, None) => None,
+            (None, i @ Some(_)) | (i @ Some(_), None) => i,
+            (Some(a), Some(b)) => Some(a + b),
+        }
+    }
+    #[inline]
+    fn collect(self) -> Self::MetricOutput {
+        u64::try_from(self.total.unwrap_or(0)).ok()
+    }
+}
+
+impl PaymentMetricAccumulator for AverageAccumulator {
+    type MetricOutput = Option<f64>;
+
+    fn add_metrics_bucket(&mut self, metrics: &PaymentMetricRow) {
+        let total = metrics
+            .total
+            .as_ref()
+            .and_then(bigdecimal::ToPrimitive::to_u32);
+        let count = metrics.count.and_then(|total| u32::try_from(total).ok());
+
+        match (total, count) {
+            (Some(total), Some(count)) => {
+                self.total += total;
+                self.count += count;
+            }
+            _ => {
+                logger::error!(message="Dropping metrics for average accumulator", metric=?metrics);
+            }
+        }
+    }
+
+    fn collect(self) -> Self::MetricOutput {
+        if self.count == 0 {
+            None
+        } else {
+            Some(f64::from(self.total) / f64::from(self.count))
+        }
+    }
+}
+
+impl PaymentMetricsAccumulator {
+    pub fn collect(self) -> PaymentMetricsBucketValue {
+        PaymentMetricsBucketValue {
+            payment_success_rate: self.payment_success_rate.collect(),
+            payment_count: self.payment_count.collect(),
+            payment_success_count: self.payment_success.collect(),
+            payment_processed_amount: self.processed_amount.collect(),
+            avg_ticket_size: self.avg_ticket_size.collect(),
+        }
+    }
+}
diff --git a/crates/router/src/analytics/payments/core.rs b/crates/router/src/analytics/payments/core.rs
new file mode 100644
index 000000000000..23eca8879a70
--- /dev/null
+++ b/crates/router/src/analytics/payments/core.rs
@@ -0,0 +1,129 @@
+use std::collections::HashMap;
+
+use api_models::analytics::{
+    payments::{MetricsBucketResponse, PaymentMetrics, PaymentMetricsBucketIdentifier},
+    AnalyticsMetadata, GetPaymentMetricRequest, MetricsResponse,
+};
+use error_stack::{IntoReport, ResultExt};
+use router_env::{
+    instrument, logger,
+    tracing::{self, Instrument},
+};
+
+use super::PaymentMetricsAccumulator;
+use crate::{
+    analytics::{
+        core::AnalyticsApiResponse, errors::AnalyticsError, metrics,
+        payments::PaymentMetricAccumulator, AnalyticsProvider,
+    },
+    services::ApplicationResponse,
+    types::domain,
+};
+
+#[instrument(skip_all)]
+pub async fn get_metrics(
+    pool: AnalyticsProvider,
+    merchant_account: domain::MerchantAccount,
+    req: GetPaymentMetricRequest,
+) -> AnalyticsApiResponse<MetricsResponse<MetricsBucketResponse>> {
+    let mut metrics_accumulator: HashMap<
+        PaymentMetricsBucketIdentifier,
+        PaymentMetricsAccumulator,
+    > = HashMap::new();
+
+    let mut set = tokio::task::JoinSet::new();
+    for metric_type in req.metrics.iter().cloned() {
+        let req = req.clone();
+        let merchant_id = merchant_account.merchant_id.clone();
+        let pool = pool.clone();
+        let task_span = tracing::debug_span!(
+            "analytics_payments_query",
+            payment_metric = metric_type.as_ref()
+        );
+        set.spawn(
+            async move {
+                let data = pool
+                    .get_payment_metrics(
+                        &metric_type,
+                        &req.group_by_names.clone(),
+                        &merchant_id,
+                        &req.filters,
+                        &req.time_series.map(|t| t.granularity),
+                        &req.time_range,
+                    )
+                    .await
+                    .change_context(AnalyticsError::UnknownError);
+                (metric_type, data)
+            }
+            .instrument(task_span),
+        );
+    }
+
+    while let Some((metric, data)) = set
+        .join_next()
+        .await
+        .transpose()
+        .into_report()
+        .change_context(AnalyticsError::UnknownError)?
+    {
+        let data = data?;
+        let attributes = &[
+            metrics::request::add_attributes("metric_type", metric.to_string()),
+            metrics::request::add_attributes(
+                "source",
+                match pool {
+                    crate::analytics::AnalyticsProvider::Sqlx(_) => "Sqlx",
+                },
+            ),
+        ];
+
+        let value = u64::try_from(data.len());
+        if let Ok(val) = value {
+            metrics::BUCKETS_FETCHED.record(&metrics::CONTEXT, val, attributes);
+            logger::debug!("Attributes: {:?}, Buckets fetched: {}", attributes, val);
+        }
+
+        for (id, value) in data {
+            logger::debug!(bucket_id=?id, bucket_value=?value, "Bucket row for metric {metric}");
+            let metrics_builder = metrics_accumulator.entry(id).or_default();
+            match metric {
+                PaymentMetrics::PaymentSuccessRate => metrics_builder
+                    .payment_success_rate
+                    .add_metrics_bucket(&value),
+                PaymentMetrics::PaymentCount => {
+                    metrics_builder.payment_count.add_metrics_bucket(&value)
+                }
+                PaymentMetrics::PaymentSuccessCount => {
+                    metrics_builder.payment_success.add_metrics_bucket(&value)
+                }
+                PaymentMetrics::PaymentProcessedAmount => {
+                    metrics_builder.processed_amount.add_metrics_bucket(&value)
+                }
+                PaymentMetrics::AvgTicketSize => {
+                    metrics_builder.avg_ticket_size.add_metrics_bucket(&value)
+                }
+            }
+        }
+
+        logger::debug!(
+            "Analytics Accumulated Results: metric: {}, results: {:#?}",
+            metric,
+            metrics_accumulator
+        );
+    }
+
+    let query_data: Vec<MetricsBucketResponse> = metrics_accumulator
+        .into_iter()
+        .map(|(id, val)| MetricsBucketResponse {
+            values: val.collect(),
+            dimensions: id,
+        })
+        .collect();
+
+    Ok(ApplicationResponse::Json(MetricsResponse {
+        query_data,
+        meta_data: [AnalyticsMetadata {
+            current_time_range: req.time_range,
+        }],
+    }))
+}
diff --git a/crates/router/src/analytics/payments/filters.rs b/crates/router/src/analytics/payments/filters.rs
new file mode 100644
index 000000000000..f009aaa76329
--- /dev/null
+++ b/crates/router/src/analytics/payments/filters.rs
@@ -0,0 +1,58 @@
+use api_models::analytics::{payments::PaymentDimensions, Granularity, TimeRange};
+use common_enums::enums::{AttemptStatus, AuthenticationType, Currency};
+use common_utils::errors::ReportSwitchExt;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use crate::analytics::{
+    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, ToSql},
+    types::{
+        AnalyticsCollection, AnalyticsDataSource, DBEnumWrapper, FiltersError, FiltersResult,
+        LoadRow,
+    },
+};
+
+pub trait PaymentFilterAnalytics: LoadRow<FilterRow> {}
+
+pub async fn get_payment_filter_for_dimension<T>(
+    dimension: PaymentDimensions,
+    merchant: &String,
+    time_range: &TimeRange,
+    pool: &T,
+) -> FiltersResult<Vec<FilterRow>>
+where
+    T: AnalyticsDataSource + PaymentFilterAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::Payment);
+
+    query_builder.add_select_column(dimension).switch()?;
+    time_range
+        .set_filter_clause(&mut query_builder)
+        .attach_printable("Error filtering time range")
+        .switch()?;
+
+    query_builder
+        .add_filter_clause("merchant_id", merchant)
+        .switch()?;
+
+    query_builder.set_distinct();
+
+    query_builder
+        .execute_query::<FilterRow, _>(pool)
+        .await
+        .change_context(FiltersError::QueryBuildingError)?
+        .change_context(FiltersError::QueryExecutionFailure)
+}
+
+#[derive(Debug, serde::Serialize, Eq, PartialEq)]
+pub struct FilterRow {
+    pub currency: Option<DBEnumWrapper<Currency>>,
+    pub status: Option<DBEnumWrapper<AttemptStatus>>,
+    pub connector: Option<String>,
+    pub authentication_type: Option<DBEnumWrapper<AuthenticationType>>,
+    pub payment_method: Option<String>,
+}
diff --git a/crates/router/src/analytics/payments/metrics.rs b/crates/router/src/analytics/payments/metrics.rs
new file mode 100644
index 000000000000..f492e5bd4df9
--- /dev/null
+++ b/crates/router/src/analytics/payments/metrics.rs
@@ -0,0 +1,137 @@
+use api_models::analytics::{
+    payments::{PaymentDimensions, PaymentFilters, PaymentMetrics, PaymentMetricsBucketIdentifier},
+    Granularity, TimeRange,
+};
+use common_enums::enums as storage_enums;
+use time::PrimitiveDateTime;
+
+use crate::analytics::{
+    query::{Aggregate, GroupByClause, ToSql},
+    types::{AnalyticsCollection, AnalyticsDataSource, DBEnumWrapper, LoadRow, MetricsResult},
+};
+
+mod avg_ticket_size;
+mod payment_count;
+mod payment_processed_amount;
+mod payment_success_count;
+mod success_rate;
+
+use avg_ticket_size::AvgTicketSize;
+use payment_count::PaymentCount;
+use payment_processed_amount::PaymentProcessedAmount;
+use payment_success_count::PaymentSuccessCount;
+use success_rate::PaymentSuccessRate;
+
+#[derive(Debug, PartialEq, Eq)]
+pub struct PaymentMetricRow {
+    pub currency: Option<DBEnumWrapper<storage_enums::Currency>>,
+    pub status: Option<DBEnumWrapper<storage_enums::AttemptStatus>>,
+    pub connector: Option<String>,
+    pub authentication_type: Option<DBEnumWrapper<storage_enums::AuthenticationType>>,
+    pub payment_method: Option<String>,
+    pub total: Option<bigdecimal::BigDecimal>,
+    pub count: Option<i64>,
+    pub start_bucket: Option<PrimitiveDateTime>,
+    pub end_bucket: Option<PrimitiveDateTime>,
+}
+
+pub trait PaymentMetricAnalytics: LoadRow<PaymentMetricRow> {}
+
+#[async_trait::async_trait]
+pub trait PaymentMetric<T>
+where
+    T: AnalyticsDataSource + PaymentMetricAnalytics,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[PaymentDimensions],
+        merchant_id: &str,
+        filters: &PaymentFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>>;
+}
+
+#[async_trait::async_trait]
+impl<T> PaymentMetric<T> for PaymentMetrics
+where
+    T: AnalyticsDataSource + PaymentMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[PaymentDimensions],
+        merchant_id: &str,
+        filters: &PaymentFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>> {
+        match self {
+            Self::PaymentSuccessRate => {
+                PaymentSuccessRate
+                    .load_metrics(
+                        dimensions,
+                        merchant_id,
+                        filters,
+                        granularity,
+                        time_range,
+                        pool,
+                    )
+                    .await
+            }
+            Self::PaymentCount => {
+                PaymentCount
+                    .load_metrics(
+                        dimensions,
+                        merchant_id,
+                        filters,
+                        granularity,
+                        time_range,
+                        pool,
+                    )
+                    .await
+            }
+            Self::PaymentSuccessCount => {
+                PaymentSuccessCount
+                    .load_metrics(
+                        dimensions,
+                        merchant_id,
+                        filters,
+                        granularity,
+                        time_range,
+                        pool,
+                    )
+                    .await
+            }
+            Self::PaymentProcessedAmount => {
+                PaymentProcessedAmount
+                    .load_metrics(
+                        dimensions,
+                        merchant_id,
+                        filters,
+                        granularity,
+                        time_range,
+                        pool,
+                    )
+                    .await
+            }
+            Self::AvgTicketSize => {
+                AvgTicketSize
+                    .load_metrics(
+                        dimensions,
+                        merchant_id,
+                        filters,
+                        granularity,
+                        time_range,
+                        pool,
+                    )
+                    .await
+            }
+        }
+    }
+}
diff --git a/crates/router/src/analytics/payments/metrics/avg_ticket_size.rs b/crates/router/src/analytics/payments/metrics/avg_ticket_size.rs
new file mode 100644
index 000000000000..2230d870e68a
--- /dev/null
+++ b/crates/router/src/analytics/payments/metrics/avg_ticket_size.rs
@@ -0,0 +1,126 @@
+use api_models::analytics::{
+    payments::{PaymentDimensions, PaymentFilters, PaymentMetricsBucketIdentifier},
+    Granularity, TimeRange,
+};
+use common_utils::errors::ReportSwitchExt;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use super::{PaymentMetric, PaymentMetricRow};
+use crate::analytics::{
+    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql},
+    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+};
+
+#[derive(Default)]
+pub(super) struct AvgTicketSize;
+
+#[async_trait::async_trait]
+impl<T> PaymentMetric<T> for AvgTicketSize
+where
+    T: AnalyticsDataSource + super::PaymentMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[PaymentDimensions],
+        merchant_id: &str,
+        filters: &PaymentFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>> {
+        let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::Payment);
+
+        for dim in dimensions.iter() {
+            query_builder.add_select_column(dim).switch()?;
+        }
+
+        query_builder
+            .add_select_column(Aggregate::Sum {
+                field: "amount",
+                alias: Some("total"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Count {
+                field: None,
+                alias: Some("count"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Min {
+                field: "created_at",
+                alias: Some("start_bucket"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Max {
+                field: "created_at",
+                alias: Some("end_bucket"),
+            })
+            .switch()?;
+
+        filters.set_filter_clause(&mut query_builder).switch()?;
+
+        query_builder
+            .add_filter_clause("merchant_id", merchant_id)
+            .switch()?;
+
+        time_range
+            .set_filter_clause(&mut query_builder)
+            .attach_printable("Error filtering time range")
+            .switch()?;
+
+        for dim in dimensions.iter() {
+            query_builder
+                .add_group_by_clause(dim)
+                .attach_printable("Error grouping by dimensions")
+                .switch()?;
+        }
+
+        if let Some(granularity) = granularity.as_ref() {
+            granularity
+                .set_group_by_clause(&mut query_builder)
+                .attach_printable("Error adding granularity")
+                .switch()?;
+        }
+
+        query_builder
+            .execute_query::<PaymentMetricRow, _>(pool)
+            .await
+            .change_context(MetricsError::QueryBuildingError)?
+            .change_context(MetricsError::QueryExecutionFailure)?
+            .into_iter()
+            .map(|i| {
+                Ok((
+                    PaymentMetricsBucketIdentifier::new(
+                        i.currency.as_ref().map(|i| i.0),
+                        i.status.as_ref().map(|i| i.0),
+                        i.connector.clone(),
+                        i.authentication_type.as_ref().map(|i| i.0),
+                        i.payment_method.clone(),
+                        TimeRange {
+                            start_time: match (granularity, i.start_bucket) {
+                                (Some(g), Some(st)) => g.clip_to_start(st)?,
+                                _ => time_range.start_time,
+                            },
+                            end_time: granularity.as_ref().map_or_else(
+                                || Ok(time_range.end_time),
+                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
+                            )?,
+                        },
+                    ),
+                    i,
+                ))
+            })
+            .collect::<error_stack::Result<
+                Vec<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>,
+                crate::analytics::query::PostProcessingError,
+            >>()
+            .change_context(MetricsError::PostProcessingFailure)
+    }
+}
diff --git a/crates/router/src/analytics/payments/metrics/payment_count.rs b/crates/router/src/analytics/payments/metrics/payment_count.rs
new file mode 100644
index 000000000000..661cec3dac36
--- /dev/null
+++ b/crates/router/src/analytics/payments/metrics/payment_count.rs
@@ -0,0 +1,117 @@
+use api_models::analytics::{
+    payments::{PaymentDimensions, PaymentFilters, PaymentMetricsBucketIdentifier},
+    Granularity, TimeRange,
+};
+use common_utils::errors::ReportSwitchExt;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use super::PaymentMetricRow;
+use crate::analytics::{
+    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql},
+    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+};
+
+#[derive(Default)]
+pub(super) struct PaymentCount;
+
+#[async_trait::async_trait]
+impl<T> super::PaymentMetric<T> for PaymentCount
+where
+    T: AnalyticsDataSource + super::PaymentMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[PaymentDimensions],
+        merchant_id: &str,
+        filters: &PaymentFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>> {
+        let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::Payment);
+
+        for dim in dimensions.iter() {
+            query_builder.add_select_column(dim).switch()?;
+        }
+
+        query_builder
+            .add_select_column(Aggregate::Count {
+                field: None,
+                alias: Some("count"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Min {
+                field: "created_at",
+                alias: Some("start_bucket"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Max {
+                field: "created_at",
+                alias: Some("end_bucket"),
+            })
+            .switch()?;
+
+        filters.set_filter_clause(&mut query_builder).switch()?;
+
+        query_builder
+            .add_filter_clause("merchant_id", merchant_id)
+            .switch()?;
+
+        time_range
+            .set_filter_clause(&mut query_builder)
+            .attach_printable("Error filtering time range")
+            .switch()?;
+
+        for dim in dimensions.iter() {
+            query_builder
+                .add_group_by_clause(dim)
+                .attach_printable("Error grouping by dimensions")
+                .switch()?;
+        }
+
+        if let Some(granularity) = granularity.as_ref() {
+            granularity
+                .set_group_by_clause(&mut query_builder)
+                .attach_printable("Error adding granularity")
+                .switch()?;
+        }
+
+        query_builder
+            .execute_query::<PaymentMetricRow, _>(pool)
+            .await
+            .change_context(MetricsError::QueryBuildingError)?
+            .change_context(MetricsError::QueryExecutionFailure)?
+            .into_iter()
+            .map(|i| {
+                Ok((
+                    PaymentMetricsBucketIdentifier::new(
+                        i.currency.as_ref().map(|i| i.0),
+                        i.status.as_ref().map(|i| i.0),
+                        i.connector.clone(),
+                        i.authentication_type.as_ref().map(|i| i.0),
+                        i.payment_method.clone(),
+                        TimeRange {
+                            start_time: match (granularity, i.start_bucket) {
+                                (Some(g), Some(st)) => g.clip_to_start(st)?,
+                                _ => time_range.start_time,
+                            },
+                            end_time: granularity.as_ref().map_or_else(
+                                || Ok(time_range.end_time),
+                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
+                            )?,
+                        },
+                    ),
+                    i,
+                ))
+            })
+            .collect::<error_stack::Result<Vec<_>, crate::analytics::query::PostProcessingError>>()
+            .change_context(MetricsError::PostProcessingFailure)
+    }
+}
diff --git a/crates/router/src/analytics/payments/metrics/payment_processed_amount.rs b/crates/router/src/analytics/payments/metrics/payment_processed_amount.rs
new file mode 100644
index 000000000000..2ec0c6f18f9c
--- /dev/null
+++ b/crates/router/src/analytics/payments/metrics/payment_processed_amount.rs
@@ -0,0 +1,128 @@
+use api_models::analytics::{
+    payments::{PaymentDimensions, PaymentFilters, PaymentMetricsBucketIdentifier},
+    Granularity, TimeRange,
+};
+use common_enums::enums as storage_enums;
+use common_utils::errors::ReportSwitchExt;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use super::PaymentMetricRow;
+use crate::analytics::{
+    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql},
+    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+};
+
+#[derive(Default)]
+pub(super) struct PaymentProcessedAmount;
+
+#[async_trait::async_trait]
+impl<T> super::PaymentMetric<T> for PaymentProcessedAmount
+where
+    T: AnalyticsDataSource + super::PaymentMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[PaymentDimensions],
+        merchant_id: &str,
+        filters: &PaymentFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>> {
+        let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::Payment);
+
+        for dim in dimensions.iter() {
+            query_builder.add_select_column(dim).switch()?;
+        }
+
+        query_builder
+            .add_select_column(Aggregate::Sum {
+                field: "amount",
+                alias: Some("total"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Min {
+                field: "created_at",
+                alias: Some("start_bucket"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Max {
+                field: "created_at",
+                alias: Some("end_bucket"),
+            })
+            .switch()?;
+
+        filters.set_filter_clause(&mut query_builder).switch()?;
+
+        query_builder
+            .add_filter_clause("merchant_id", merchant_id)
+            .switch()?;
+
+        time_range
+            .set_filter_clause(&mut query_builder)
+            .attach_printable("Error filtering time range")
+            .switch()?;
+
+        for dim in dimensions.iter() {
+            query_builder
+                .add_group_by_clause(dim)
+                .attach_printable("Error grouping by dimensions")
+                .switch()?;
+        }
+
+        if let Some(granularity) = granularity.as_ref() {
+            granularity
+                .set_group_by_clause(&mut query_builder)
+                .attach_printable("Error adding granularity")
+                .switch()?;
+        }
+
+        query_builder
+            .add_filter_clause(
+                PaymentDimensions::PaymentStatus,
+                storage_enums::AttemptStatus::Charged,
+            )
+            .switch()?;
+
+        query_builder
+            .execute_query::<PaymentMetricRow, _>(pool)
+            .await
+            .change_context(MetricsError::QueryBuildingError)?
+            .change_context(MetricsError::QueryExecutionFailure)?
+            .into_iter()
+            .map(|i| {
+                Ok((
+                    PaymentMetricsBucketIdentifier::new(
+                        i.currency.as_ref().map(|i| i.0),
+                        None,
+                        i.connector.clone(),
+                        i.authentication_type.as_ref().map(|i| i.0),
+                        i.payment_method.clone(),
+                        TimeRange {
+                            start_time: match (granularity, i.start_bucket) {
+                                (Some(g), Some(st)) => g.clip_to_start(st)?,
+                                _ => time_range.start_time,
+                            },
+                            end_time: granularity.as_ref().map_or_else(
+                                || Ok(time_range.end_time),
+                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
+                            )?,
+                        },
+                    ),
+                    i,
+                ))
+            })
+            .collect::<error_stack::Result<
+                Vec<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>,
+                crate::analytics::query::PostProcessingError,
+            >>()
+            .change_context(MetricsError::PostProcessingFailure)
+    }
+}
diff --git a/crates/router/src/analytics/payments/metrics/payment_success_count.rs b/crates/router/src/analytics/payments/metrics/payment_success_count.rs
new file mode 100644
index 000000000000..8245fe7aeb88
--- /dev/null
+++ b/crates/router/src/analytics/payments/metrics/payment_success_count.rs
@@ -0,0 +1,127 @@
+use api_models::analytics::{
+    payments::{PaymentDimensions, PaymentFilters, PaymentMetricsBucketIdentifier},
+    Granularity, TimeRange,
+};
+use common_enums::enums as storage_enums;
+use common_utils::errors::ReportSwitchExt;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use super::PaymentMetricRow;
+use crate::analytics::{
+    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql},
+    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+};
+
+#[derive(Default)]
+pub(super) struct PaymentSuccessCount;
+
+#[async_trait::async_trait]
+impl<T> super::PaymentMetric<T> for PaymentSuccessCount
+where
+    T: AnalyticsDataSource + super::PaymentMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[PaymentDimensions],
+        merchant_id: &str,
+        filters: &PaymentFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>> {
+        let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::Payment);
+
+        for dim in dimensions.iter() {
+            query_builder.add_select_column(dim).switch()?;
+        }
+
+        query_builder
+            .add_select_column(Aggregate::Count {
+                field: None,
+                alias: Some("count"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Min {
+                field: "created_at",
+                alias: Some("start_bucket"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Max {
+                field: "created_at",
+                alias: Some("end_bucket"),
+            })
+            .switch()?;
+
+        filters.set_filter_clause(&mut query_builder).switch()?;
+
+        query_builder
+            .add_filter_clause("merchant_id", merchant_id)
+            .switch()?;
+
+        time_range
+            .set_filter_clause(&mut query_builder)
+            .attach_printable("Error filtering time range")
+            .switch()?;
+
+        for dim in dimensions.iter() {
+            query_builder
+                .add_group_by_clause(dim)
+                .attach_printable("Error grouping by dimensions")
+                .switch()?;
+        }
+
+        if let Some(granularity) = granularity.as_ref() {
+            granularity
+                .set_group_by_clause(&mut query_builder)
+                .attach_printable("Error adding granularity")
+                .switch()?;
+        }
+
+        query_builder
+            .add_filter_clause(
+                PaymentDimensions::PaymentStatus,
+                storage_enums::AttemptStatus::Charged,
+            )
+            .switch()?;
+        query_builder
+            .execute_query::<PaymentMetricRow, _>(pool)
+            .await
+            .change_context(MetricsError::QueryBuildingError)?
+            .change_context(MetricsError::QueryExecutionFailure)?
+            .into_iter()
+            .map(|i| {
+                Ok((
+                    PaymentMetricsBucketIdentifier::new(
+                        i.currency.as_ref().map(|i| i.0),
+                        None,
+                        i.connector.clone(),
+                        i.authentication_type.as_ref().map(|i| i.0),
+                        i.payment_method.clone(),
+                        TimeRange {
+                            start_time: match (granularity, i.start_bucket) {
+                                (Some(g), Some(st)) => g.clip_to_start(st)?,
+                                _ => time_range.start_time,
+                            },
+                            end_time: granularity.as_ref().map_or_else(
+                                || Ok(time_range.end_time),
+                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
+                            )?,
+                        },
+                    ),
+                    i,
+                ))
+            })
+            .collect::<error_stack::Result<
+                Vec<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>,
+                crate::analytics::query::PostProcessingError,
+            >>()
+            .change_context(MetricsError::PostProcessingFailure)
+    }
+}
diff --git a/crates/router/src/analytics/payments/metrics/success_rate.rs b/crates/router/src/analytics/payments/metrics/success_rate.rs
new file mode 100644
index 000000000000..c63956d4b157
--- /dev/null
+++ b/crates/router/src/analytics/payments/metrics/success_rate.rs
@@ -0,0 +1,123 @@
+use api_models::analytics::{
+    payments::{PaymentDimensions, PaymentFilters, PaymentMetricsBucketIdentifier},
+    Granularity, TimeRange,
+};
+use common_utils::errors::ReportSwitchExt;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use super::PaymentMetricRow;
+use crate::analytics::{
+    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql},
+    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+};
+
+#[derive(Default)]
+pub(super) struct PaymentSuccessRate;
+
+#[async_trait::async_trait]
+impl<T> super::PaymentMetric<T> for PaymentSuccessRate
+where
+    T: AnalyticsDataSource + super::PaymentMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[PaymentDimensions],
+        merchant_id: &str,
+        filters: &PaymentFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>> {
+        let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::Payment);
+        let mut dimensions = dimensions.to_vec();
+
+        dimensions.push(PaymentDimensions::PaymentStatus);
+
+        for dim in dimensions.iter() {
+            query_builder.add_select_column(dim).switch()?;
+        }
+
+        query_builder
+            .add_select_column(Aggregate::Count {
+                field: None,
+                alias: Some("count"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Min {
+                field: "created_at",
+                alias: Some("start_bucket"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Max {
+                field: "created_at",
+                alias: Some("end_bucket"),
+            })
+            .switch()?;
+
+        filters.set_filter_clause(&mut query_builder).switch()?;
+
+        query_builder
+            .add_filter_clause("merchant_id", merchant_id)
+            .switch()?;
+
+        time_range
+            .set_filter_clause(&mut query_builder)
+            .attach_printable("Error filtering time range")
+            .switch()?;
+
+        for dim in dimensions.iter() {
+            query_builder
+                .add_group_by_clause(dim)
+                .attach_printable("Error grouping by dimensions")
+                .switch()?;
+        }
+
+        if let Some(granularity) = granularity.as_ref() {
+            granularity
+                .set_group_by_clause(&mut query_builder)
+                .attach_printable("Error adding granularity")
+                .switch()?;
+        }
+
+        query_builder
+            .execute_query::<PaymentMetricRow, _>(pool)
+            .await
+            .change_context(MetricsError::QueryBuildingError)?
+            .change_context(MetricsError::QueryExecutionFailure)?
+            .into_iter()
+            .map(|i| {
+                Ok((
+                    PaymentMetricsBucketIdentifier::new(
+                        i.currency.as_ref().map(|i| i.0),
+                        None,
+                        i.connector.clone(),
+                        i.authentication_type.as_ref().map(|i| i.0),
+                        i.payment_method.clone(),
+                        TimeRange {
+                            start_time: match (granularity, i.start_bucket) {
+                                (Some(g), Some(st)) => g.clip_to_start(st)?,
+                                _ => time_range.start_time,
+                            },
+                            end_time: granularity.as_ref().map_or_else(
+                                || Ok(time_range.end_time),
+                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
+                            )?,
+                        },
+                    ),
+                    i,
+                ))
+            })
+            .collect::<error_stack::Result<
+                Vec<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>,
+                crate::analytics::query::PostProcessingError,
+            >>()
+            .change_context(MetricsError::PostProcessingFailure)
+    }
+}
diff --git a/crates/router/src/analytics/payments/types.rs b/crates/router/src/analytics/payments/types.rs
new file mode 100644
index 000000000000..fdfbedef383d
--- /dev/null
+++ b/crates/router/src/analytics/payments/types.rs
@@ -0,0 +1,46 @@
+use api_models::analytics::payments::{PaymentDimensions, PaymentFilters};
+use error_stack::ResultExt;
+
+use crate::analytics::{
+    query::{QueryBuilder, QueryFilter, QueryResult, ToSql},
+    types::{AnalyticsCollection, AnalyticsDataSource},
+};
+
+impl<T> QueryFilter<T> for PaymentFilters
+where
+    T: AnalyticsDataSource,
+    AnalyticsCollection: ToSql<T>,
+{
+    fn set_filter_clause(&self, builder: &mut QueryBuilder<T>) -> QueryResult<()> {
+        if !self.currency.is_empty() {
+            builder
+                .add_filter_in_range_clause(PaymentDimensions::Currency, &self.currency)
+                .attach_printable("Error adding currency filter")?;
+        }
+
+        if !self.status.is_empty() {
+            builder
+                .add_filter_in_range_clause(PaymentDimensions::PaymentStatus, &self.status)
+                .attach_printable("Error adding payment status filter")?;
+        }
+
+        if !self.connector.is_empty() {
+            builder
+                .add_filter_in_range_clause(PaymentDimensions::Connector, &self.connector)
+                .attach_printable("Error adding connector filter")?;
+        }
+
+        if !self.auth_type.is_empty() {
+            builder
+                .add_filter_in_range_clause(PaymentDimensions::AuthType, &self.auth_type)
+                .attach_printable("Error adding auth type filter")?;
+        }
+
+        if !self.payment_method.is_empty() {
+            builder
+                .add_filter_in_range_clause(PaymentDimensions::PaymentMethod, &self.payment_method)
+                .attach_printable("Error adding payment method filter")?;
+        }
+        Ok(())
+    }
+}
diff --git a/crates/router/src/analytics/query.rs b/crates/router/src/analytics/query.rs
new file mode 100644
index 000000000000..b1f621d8153d
--- /dev/null
+++ b/crates/router/src/analytics/query.rs
@@ -0,0 +1,533 @@
+#![allow(dead_code)]
+use std::marker::PhantomData;
+
+use api_models::{
+    analytics::{
+        self as analytics_api,
+        payments::PaymentDimensions,
+        refunds::{RefundDimensions, RefundType},
+        Granularity,
+    },
+    enums::Connector,
+    refunds::RefundStatus,
+};
+use common_enums::{
+    enums as storage_enums,
+    enums::{AttemptStatus, AuthenticationType, Currency, PaymentMethod},
+};
+use common_utils::errors::{CustomResult, ParsingError};
+use error_stack::{IntoReport, ResultExt};
+use router_env::logger;
+
+use super::types::{AnalyticsCollection, AnalyticsDataSource, LoadRow};
+use crate::analytics::types::QueryExecutionError;
+pub type QueryResult<T> = error_stack::Result<T, QueryBuildingError>;
+pub trait QueryFilter<T>
+where
+    T: AnalyticsDataSource,
+    AnalyticsCollection: ToSql<T>,
+{
+    fn set_filter_clause(&self, builder: &mut QueryBuilder<T>) -> QueryResult<()>;
+}
+
+pub trait GroupByClause<T>
+where
+    T: AnalyticsDataSource,
+    AnalyticsCollection: ToSql<T>,
+{
+    fn set_group_by_clause(&self, builder: &mut QueryBuilder<T>) -> QueryResult<()>;
+}
+
+pub trait SeriesBucket {
+    type SeriesType;
+    type GranularityLevel;
+
+    fn get_lowest_common_granularity_level(&self) -> Self::GranularityLevel;
+
+    fn get_bucket_size(&self) -> u8;
+
+    fn clip_to_start(
+        &self,
+        value: Self::SeriesType,
+    ) -> error_stack::Result<Self::SeriesType, PostProcessingError>;
+
+    fn clip_to_end(
+        &self,
+        value: Self::SeriesType,
+    ) -> error_stack::Result<Self::SeriesType, PostProcessingError>;
+}
+
+impl<T> QueryFilter<T> for analytics_api::TimeRange
+where
+    T: AnalyticsDataSource,
+    time::PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+{
+    fn set_filter_clause(&self, builder: &mut QueryBuilder<T>) -> QueryResult<()> {
+        builder.add_custom_filter_clause("created_at", self.start_time, FilterTypes::Gte)?;
+        if let Some(end) = self.end_time {
+            builder.add_custom_filter_clause("created_at", end, FilterTypes::Lte)?;
+        }
+        Ok(())
+    }
+}
+
+impl GroupByClause<super::SqlxClient> for Granularity {
+    fn set_group_by_clause(
+        &self,
+        builder: &mut QueryBuilder<super::SqlxClient>,
+    ) -> QueryResult<()> {
+        let trunc_scale = self.get_lowest_common_granularity_level();
+
+        let granularity_bucket_scale = match self {
+            Self::OneMin => None,
+            Self::FiveMin | Self::FifteenMin | Self::ThirtyMin => Some("minute"),
+            Self::OneHour | Self::OneDay => None,
+        };
+
+        let granularity_divisor = self.get_bucket_size();
+
+        builder
+            .add_group_by_clause(format!("DATE_TRUNC('{trunc_scale}', modified_at)"))
+            .attach_printable("Error adding time prune group by")?;
+        if let Some(scale) = granularity_bucket_scale {
+            builder
+                .add_group_by_clause(format!(
+                    "FLOOR(DATE_PART('{scale}', modified_at)/{granularity_divisor})"
+                ))
+                .attach_printable("Error adding time binning group by")?;
+        }
+        Ok(())
+    }
+}
+
+#[derive(strum::Display)]
+#[strum(serialize_all = "lowercase")]
+pub enum TimeGranularityLevel {
+    Minute,
+    Hour,
+    Day,
+}
+
+impl SeriesBucket for Granularity {
+    type SeriesType = time::PrimitiveDateTime;
+
+    type GranularityLevel = TimeGranularityLevel;
+
+    fn get_lowest_common_granularity_level(&self) -> Self::GranularityLevel {
+        match self {
+            Self::OneMin => TimeGranularityLevel::Minute,
+            Self::FiveMin | Self::FifteenMin | Self::ThirtyMin | Self::OneHour => {
+                TimeGranularityLevel::Hour
+            }
+            Self::OneDay => TimeGranularityLevel::Day,
+        }
+    }
+
+    fn get_bucket_size(&self) -> u8 {
+        match self {
+            Self::OneMin => 60,
+            Self::FiveMin => 5,
+            Self::FifteenMin => 15,
+            Self::ThirtyMin => 30,
+            Self::OneHour => 60,
+            Self::OneDay => 24,
+        }
+    }
+
+    fn clip_to_start(
+        &self,
+        value: Self::SeriesType,
+    ) -> error_stack::Result<Self::SeriesType, PostProcessingError> {
+        let clip_start = |value: u8, modulo: u8| -> u8 { value - value % modulo };
+
+        let clipped_time = match (
+            self.get_lowest_common_granularity_level(),
+            self.get_bucket_size(),
+        ) {
+            (TimeGranularityLevel::Minute, i) => time::Time::MIDNIGHT
+                .replace_second(clip_start(value.second(), i))
+                .and_then(|t| t.replace_minute(value.minute()))
+                .and_then(|t| t.replace_hour(value.hour())),
+            (TimeGranularityLevel::Hour, i) => time::Time::MIDNIGHT
+                .replace_minute(clip_start(value.minute(), i))
+                .and_then(|t| t.replace_hour(value.hour())),
+            (TimeGranularityLevel::Day, i) => {
+                time::Time::MIDNIGHT.replace_hour(clip_start(value.hour(), i))
+            }
+        }
+        .into_report()
+        .change_context(PostProcessingError::BucketClipping)?;
+
+        Ok(value.replace_time(clipped_time))
+    }
+
+    fn clip_to_end(
+        &self,
+        value: Self::SeriesType,
+    ) -> error_stack::Result<Self::SeriesType, PostProcessingError> {
+        let clip_end = |value: u8, modulo: u8| -> u8 { value + modulo - 1 - value % modulo };
+
+        let clipped_time = match (
+            self.get_lowest_common_granularity_level(),
+            self.get_bucket_size(),
+        ) {
+            (TimeGranularityLevel::Minute, i) => time::Time::MIDNIGHT
+                .replace_second(clip_end(value.second(), i))
+                .and_then(|t| t.replace_minute(value.minute()))
+                .and_then(|t| t.replace_hour(value.hour())),
+            (TimeGranularityLevel::Hour, i) => time::Time::MIDNIGHT
+                .replace_minute(clip_end(value.minute(), i))
+                .and_then(|t| t.replace_hour(value.hour())),
+            (TimeGranularityLevel::Day, i) => {
+                time::Time::MIDNIGHT.replace_hour(clip_end(value.hour(), i))
+            }
+        }
+        .into_report()
+        .change_context(PostProcessingError::BucketClipping)
+        .attach_printable_lazy(|| format!("Bucket Clip Error: {value}"))?;
+
+        Ok(value.replace_time(clipped_time))
+    }
+}
+
+#[derive(thiserror::Error, Debug)]
+pub enum QueryBuildingError {
+    #[allow(dead_code)]
+    #[error("Not Implemented: {0}")]
+    NotImplemented(String),
+    #[error("Failed to Serialize to SQL")]
+    SqlSerializeError,
+    #[error("Failed to build sql query: {0}")]
+    InvalidQuery(&'static str),
+}
+
+#[derive(thiserror::Error, Debug)]
+pub enum PostProcessingError {
+    #[error("Error Clipping values to bucket sizes")]
+    BucketClipping,
+}
+
+#[derive(Debug)]
+pub enum Aggregate<R> {
+    Count {
+        field: Option<R>,
+        alias: Option<&'static str>,
+    },
+    Sum {
+        field: R,
+        alias: Option<&'static str>,
+    },
+    Min {
+        field: R,
+        alias: Option<&'static str>,
+    },
+    Max {
+        field: R,
+        alias: Option<&'static str>,
+    },
+}
+
+#[derive(Debug)]
+pub struct QueryBuilder<T>
+where
+    T: AnalyticsDataSource,
+    AnalyticsCollection: ToSql<T>,
+{
+    columns: Vec<String>,
+    filters: Vec<(String, FilterTypes, String)>,
+    group_by: Vec<String>,
+    having: Option<Vec<(String, FilterTypes, String)>>,
+    table: AnalyticsCollection,
+    distinct: bool,
+    db_type: PhantomData<T>,
+}
+
+pub trait ToSql<T: AnalyticsDataSource> {
+    fn to_sql(&self) -> error_stack::Result<String, ParsingError>;
+}
+
+/// Implement `ToSql` on arrays of types that impl `ToString`.
+macro_rules! impl_to_sql_for_to_string {
+    ($($type:ty),+) => {
+        $(
+            impl<T: AnalyticsDataSource> ToSql<T> for $type {
+                fn to_sql(&self) -> error_stack::Result<String, ParsingError> {
+                    Ok(self.to_string())
+                }
+            }
+        )+
+     };
+}
+
+impl_to_sql_for_to_string!(
+    String,
+    &str,
+    &PaymentDimensions,
+    &RefundDimensions,
+    PaymentDimensions,
+    RefundDimensions,
+    PaymentMethod,
+    AuthenticationType,
+    Connector,
+    AttemptStatus,
+    RefundStatus,
+    storage_enums::RefundStatus,
+    Currency,
+    RefundType,
+    &String,
+    &bool,
+    &u64
+);
+
+#[allow(dead_code)]
+#[derive(Debug)]
+pub enum FilterTypes {
+    Equal,
+    EqualBool,
+    In,
+    Gte,
+    Lte,
+    Gt,
+}
+
+impl<T> QueryBuilder<T>
+where
+    T: AnalyticsDataSource,
+    AnalyticsCollection: ToSql<T>,
+{
+    pub fn new(table: AnalyticsCollection) -> Self {
+        Self {
+            columns: Default::default(),
+            filters: Default::default(),
+            group_by: Default::default(),
+            having: Default::default(),
+            table,
+            distinct: Default::default(),
+            db_type: Default::default(),
+        }
+    }
+
+    pub fn add_select_column(&mut self, column: impl ToSql<T>) -> QueryResult<()> {
+        self.columns.push(
+            column
+                .to_sql()
+                .change_context(QueryBuildingError::SqlSerializeError)
+                .attach_printable("Error serializing select column")?,
+        );
+        Ok(())
+    }
+
+    pub fn set_distinct(&mut self) {
+        self.distinct = true
+    }
+
+    pub fn add_filter_clause(
+        &mut self,
+        key: impl ToSql<T>,
+        value: impl ToSql<T>,
+    ) -> QueryResult<()> {
+        self.add_custom_filter_clause(key, value, FilterTypes::Equal)
+    }
+
+    pub fn add_bool_filter_clause(
+        &mut self,
+        key: impl ToSql<T>,
+        value: impl ToSql<T>,
+    ) -> QueryResult<()> {
+        self.add_custom_filter_clause(key, value, FilterTypes::EqualBool)
+    }
+
+    pub fn add_custom_filter_clause(
+        &mut self,
+        lhs: impl ToSql<T>,
+        rhs: impl ToSql<T>,
+        comparison: FilterTypes,
+    ) -> QueryResult<()> {
+        self.filters.push((
+            lhs.to_sql()
+                .change_context(QueryBuildingError::SqlSerializeError)
+                .attach_printable("Error serializing filter key")?,
+            comparison,
+            rhs.to_sql()
+                .change_context(QueryBuildingError::SqlSerializeError)
+                .attach_printable("Error serializing filter value")?,
+        ));
+        Ok(())
+    }
+
+    pub fn add_filter_in_range_clause(
+        &mut self,
+        key: impl ToSql<T>,
+        values: &[impl ToSql<T>],
+    ) -> QueryResult<()> {
+        let list = values
+            .iter()
+            .map(|i| {
+                // trimming whitespaces from the filter values received in request, to prevent a possibility of an SQL injection
+                i.to_sql().map(|s| {
+                    let trimmed_str = s.replace(' ', "");
+                    format!("'{trimmed_str}'")
+                })
+            })
+            .collect::<error_stack::Result<Vec<String>, ParsingError>>()
+            .change_context(QueryBuildingError::SqlSerializeError)
+            .attach_printable("Error serializing range filter value")?
+            .join(", ");
+        self.add_custom_filter_clause(key, list, FilterTypes::In)
+    }
+
+    pub fn add_group_by_clause(&mut self, column: impl ToSql<T>) -> QueryResult<()> {
+        self.group_by.push(
+            column
+                .to_sql()
+                .change_context(QueryBuildingError::SqlSerializeError)
+                .attach_printable("Error serializing group by field")?,
+        );
+        Ok(())
+    }
+
+    pub fn add_granularity_in_mins(&mut self, granularity: &Granularity) -> QueryResult<()> {
+        let interval = match granularity {
+            Granularity::OneMin => "1",
+            Granularity::FiveMin => "5",
+            Granularity::FifteenMin => "15",
+            Granularity::ThirtyMin => "30",
+            Granularity::OneHour => "60",
+            Granularity::OneDay => "1440",
+        };
+        let _ = self.add_select_column(format!(
+            "toStartOfInterval(created_at, INTERVAL {interval} MINUTE) as time_bucket"
+        ));
+        Ok(())
+    }
+
+    fn get_filter_clause(&self) -> String {
+        self.filters
+            .iter()
+            .map(|(l, op, r)| match op {
+                FilterTypes::EqualBool => format!("{l} = {r}"),
+                FilterTypes::Equal => format!("{l} = '{r}'"),
+                FilterTypes::In => format!("{l} IN ({r})"),
+                FilterTypes::Gte => format!("{l} >= '{r}'"),
+                FilterTypes::Gt => format!("{l} > {r}"),
+                FilterTypes::Lte => format!("{l} <= '{r}'"),
+            })
+            .collect::<Vec<String>>()
+            .join(" AND ")
+    }
+
+    fn get_select_clause(&self) -> String {
+        self.columns.join(", ")
+    }
+
+    fn get_group_by_clause(&self) -> String {
+        self.group_by.join(", ")
+    }
+
+    #[allow(dead_code)]
+    pub fn add_having_clause<R>(
+        &mut self,
+        aggregate: Aggregate<R>,
+        filter_type: FilterTypes,
+        value: impl ToSql<T>,
+    ) -> QueryResult<()>
+    where
+        Aggregate<R>: ToSql<T>,
+    {
+        let aggregate = aggregate
+            .to_sql()
+            .change_context(QueryBuildingError::SqlSerializeError)
+            .attach_printable("Error serializing having aggregate")?;
+        let value = value
+            .to_sql()
+            .change_context(QueryBuildingError::SqlSerializeError)
+            .attach_printable("Error serializing having value")?;
+        let entry = (aggregate, filter_type, value);
+        if let Some(having) = &mut self.having {
+            having.push(entry);
+        } else {
+            self.having = Some(vec![entry]);
+        }
+        Ok(())
+    }
+
+    pub fn get_filter_type_clause(&self) -> Option<String> {
+        self.having.as_ref().map(|vec| {
+            vec.iter()
+                .map(|(l, op, r)| match op {
+                    FilterTypes::Equal | FilterTypes::EqualBool => format!("{l} = {r}"),
+                    FilterTypes::In => format!("{l} IN ({r})"),
+                    FilterTypes::Gte => format!("{l} >= {r}"),
+                    FilterTypes::Lte => format!("{l} < {r}"),
+                    FilterTypes::Gt => format!("{l} > {r}"),
+                })
+                .collect::<Vec<String>>()
+                .join(" AND ")
+        })
+    }
+
+    pub fn build_query(&mut self) -> QueryResult<String>
+    where
+        Aggregate<&'static str>: ToSql<T>,
+    {
+        if self.columns.is_empty() {
+            Err(QueryBuildingError::InvalidQuery(
+                "No select fields provided",
+            ))
+            .into_report()?;
+        }
+        let mut query = String::from("SELECT ");
+
+        if self.distinct {
+            query.push_str("DISTINCT ");
+        }
+
+        query.push_str(&self.get_select_clause());
+
+        query.push_str(" FROM ");
+
+        query.push_str(
+            &self
+                .table
+                .to_sql()
+                .change_context(QueryBuildingError::SqlSerializeError)
+                .attach_printable("Error serializing table value")?,
+        );
+
+        if !self.filters.is_empty() {
+            query.push_str(" WHERE ");
+            query.push_str(&self.get_filter_clause());
+        }
+
+        if !self.group_by.is_empty() {
+            query.push_str(" GROUP BY ");
+            query.push_str(&self.get_group_by_clause());
+        }
+
+        if self.having.is_some() {
+            if let Some(condition) = self.get_filter_type_clause() {
+                query.push_str(" HAVING ");
+                query.push_str(condition.as_str());
+            }
+        }
+        Ok(query)
+    }
+
+    pub async fn execute_query<R, P: AnalyticsDataSource>(
+        &mut self,
+        store: &P,
+    ) -> CustomResult<CustomResult<Vec<R>, QueryExecutionError>, QueryBuildingError>
+    where
+        P: LoadRow<R>,
+        Aggregate<&'static str>: ToSql<T>,
+    {
+        let query = self
+            .build_query()
+            .change_context(QueryBuildingError::SqlSerializeError)
+            .attach_printable("Failed to execute query")?;
+        logger::debug!(?query);
+        Ok(store.load_results(query.as_str()).await)
+    }
+}
diff --git a/crates/router/src/analytics/refunds.rs b/crates/router/src/analytics/refunds.rs
new file mode 100644
index 000000000000..a8b52effe76d
--- /dev/null
+++ b/crates/router/src/analytics/refunds.rs
@@ -0,0 +1,10 @@
+pub mod accumulator;
+mod core;
+
+pub mod filters;
+pub mod metrics;
+pub mod types;
+pub use accumulator::{RefundMetricAccumulator, RefundMetricsAccumulator};
+
+pub trait RefundAnalytics: metrics::RefundMetricAnalytics {}
+pub use self::core::get_metrics;
diff --git a/crates/router/src/analytics/refunds/accumulator.rs b/crates/router/src/analytics/refunds/accumulator.rs
new file mode 100644
index 000000000000..3d0c0e659f6c
--- /dev/null
+++ b/crates/router/src/analytics/refunds/accumulator.rs
@@ -0,0 +1,110 @@
+use api_models::analytics::refunds::RefundMetricsBucketValue;
+use common_enums::enums as storage_enums;
+
+use super::metrics::RefundMetricRow;
+#[derive(Debug, Default)]
+pub struct RefundMetricsAccumulator {
+    pub refund_success_rate: SuccessRateAccumulator,
+    pub refund_count: CountAccumulator,
+    pub refund_success: CountAccumulator,
+    pub processed_amount: SumAccumulator,
+}
+
+#[derive(Debug, Default)]
+pub struct SuccessRateAccumulator {
+    pub success: i64,
+    pub total: i64,
+}
+
+#[derive(Debug, Default)]
+#[repr(transparent)]
+pub struct CountAccumulator {
+    pub count: Option<i64>,
+}
+
+#[derive(Debug, Default)]
+#[repr(transparent)]
+pub struct SumAccumulator {
+    pub total: Option<i64>,
+}
+
+pub trait RefundMetricAccumulator {
+    type MetricOutput;
+
+    fn add_metrics_bucket(&mut self, metrics: &RefundMetricRow);
+
+    fn collect(self) -> Self::MetricOutput;
+}
+
+impl RefundMetricAccumulator for CountAccumulator {
+    type MetricOutput = Option<u64>;
+    #[inline]
+    fn add_metrics_bucket(&mut self, metrics: &RefundMetricRow) {
+        self.count = match (self.count, metrics.count) {
+            (None, None) => None,
+            (None, i @ Some(_)) | (i @ Some(_), None) => i,
+            (Some(a), Some(b)) => Some(a + b),
+        }
+    }
+    #[inline]
+    fn collect(self) -> Self::MetricOutput {
+        self.count.and_then(|i| u64::try_from(i).ok())
+    }
+}
+
+impl RefundMetricAccumulator for SumAccumulator {
+    type MetricOutput = Option<u64>;
+    #[inline]
+    fn add_metrics_bucket(&mut self, metrics: &RefundMetricRow) {
+        self.total = match (
+            self.total,
+            metrics
+                .total
+                .as_ref()
+                .and_then(bigdecimal::ToPrimitive::to_i64),
+        ) {
+            (None, None) => None,
+            (None, i @ Some(_)) | (i @ Some(_), None) => i,
+            (Some(a), Some(b)) => Some(a + b),
+        }
+    }
+    #[inline]
+    fn collect(self) -> Self::MetricOutput {
+        self.total.and_then(|i| u64::try_from(i).ok())
+    }
+}
+
+impl RefundMetricAccumulator for SuccessRateAccumulator {
+    type MetricOutput = Option<f64>;
+
+    fn add_metrics_bucket(&mut self, metrics: &RefundMetricRow) {
+        if let Some(ref refund_status) = metrics.refund_status {
+            if refund_status.as_ref() == &storage_enums::RefundStatus::Success {
+                self.success += metrics.count.unwrap_or_default();
+            }
+        };
+        self.total += metrics.count.unwrap_or_default();
+    }
+
+    fn collect(self) -> Self::MetricOutput {
+        if self.total <= 0 {
+            None
+        } else {
+            Some(
+                f64::from(u32::try_from(self.success).ok()?) * 100.0
+                    / f64::from(u32::try_from(self.total).ok()?),
+            )
+        }
+    }
+}
+
+impl RefundMetricsAccumulator {
+    pub fn collect(self) -> RefundMetricsBucketValue {
+        RefundMetricsBucketValue {
+            refund_success_rate: self.refund_success_rate.collect(),
+            refund_count: self.refund_count.collect(),
+            refund_success_count: self.refund_success.collect(),
+            refund_processed_amount: self.processed_amount.collect(),
+        }
+    }
+}
diff --git a/crates/router/src/analytics/refunds/core.rs b/crates/router/src/analytics/refunds/core.rs
new file mode 100644
index 000000000000..4c2d2c394181
--- /dev/null
+++ b/crates/router/src/analytics/refunds/core.rs
@@ -0,0 +1,104 @@
+use std::collections::HashMap;
+
+use api_models::analytics::{
+    refunds::{RefundMetrics, RefundMetricsBucketIdentifier, RefundMetricsBucketResponse},
+    AnalyticsMetadata, GetRefundMetricRequest, MetricsResponse,
+};
+use error_stack::{IntoReport, ResultExt};
+use router_env::{
+    logger,
+    tracing::{self, Instrument},
+};
+
+use super::RefundMetricsAccumulator;
+use crate::{
+    analytics::{
+        core::AnalyticsApiResponse, errors::AnalyticsError, refunds::RefundMetricAccumulator,
+        AnalyticsProvider,
+    },
+    services::ApplicationResponse,
+    types::domain,
+};
+
+pub async fn get_metrics(
+    pool: AnalyticsProvider,
+    merchant_account: domain::MerchantAccount,
+    req: GetRefundMetricRequest,
+) -> AnalyticsApiResponse<MetricsResponse<RefundMetricsBucketResponse>> {
+    let mut metrics_accumulator: HashMap<RefundMetricsBucketIdentifier, RefundMetricsAccumulator> =
+        HashMap::new();
+    let mut set = tokio::task::JoinSet::new();
+    for metric_type in req.metrics.iter().cloned() {
+        let req = req.clone();
+        let merchant_id = merchant_account.merchant_id.clone();
+        let pool = pool.clone();
+        let task_span = tracing::debug_span!(
+            "analytics_refund_query",
+            refund_metric = metric_type.as_ref()
+        );
+        set.spawn(
+            async move {
+                let data = pool
+                    .get_refund_metrics(
+                        &metric_type,
+                        &req.group_by_names.clone(),
+                        &merchant_id,
+                        &req.filters,
+                        &req.time_series.map(|t| t.granularity),
+                        &req.time_range,
+                    )
+                    .await
+                    .change_context(AnalyticsError::UnknownError);
+                (metric_type, data)
+            }
+            .instrument(task_span),
+        );
+    }
+
+    while let Some((metric, data)) = set
+        .join_next()
+        .await
+        .transpose()
+        .into_report()
+        .change_context(AnalyticsError::UnknownError)?
+    {
+        for (id, value) in data? {
+            logger::debug!(bucket_id=?id, bucket_value=?value, "Bucket row for metric {metric}");
+            let metrics_builder = metrics_accumulator.entry(id).or_default();
+            match metric {
+                RefundMetrics::RefundSuccessRate => metrics_builder
+                    .refund_success_rate
+                    .add_metrics_bucket(&value),
+                RefundMetrics::RefundCount => {
+                    metrics_builder.refund_count.add_metrics_bucket(&value)
+                }
+                RefundMetrics::RefundSuccessCount => {
+                    metrics_builder.refund_success.add_metrics_bucket(&value)
+                }
+                RefundMetrics::RefundProcessedAmount => {
+                    metrics_builder.processed_amount.add_metrics_bucket(&value)
+                }
+            }
+        }
+
+        logger::debug!(
+            "Analytics Accumulated Results: metric: {}, results: {:#?}",
+            metric,
+            metrics_accumulator
+        );
+    }
+    let query_data: Vec<RefundMetricsBucketResponse> = metrics_accumulator
+        .into_iter()
+        .map(|(id, val)| RefundMetricsBucketResponse {
+            values: val.collect(),
+            dimensions: id,
+        })
+        .collect();
+
+    Ok(ApplicationResponse::Json(MetricsResponse {
+        query_data,
+        meta_data: [AnalyticsMetadata {
+            current_time_range: req.time_range,
+        }],
+    }))
+}
diff --git a/crates/router/src/analytics/refunds/filters.rs b/crates/router/src/analytics/refunds/filters.rs
new file mode 100644
index 000000000000..6b45e9194fad
--- /dev/null
+++ b/crates/router/src/analytics/refunds/filters.rs
@@ -0,0 +1,59 @@
+use api_models::analytics::{
+    refunds::{RefundDimensions, RefundType},
+    Granularity, TimeRange,
+};
+use common_enums::enums::{Currency, RefundStatus};
+use common_utils::errors::ReportSwitchExt;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use crate::analytics::{
+    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, ToSql},
+    types::{
+        AnalyticsCollection, AnalyticsDataSource, DBEnumWrapper, FiltersError, FiltersResult,
+        LoadRow,
+    },
+};
+pub trait RefundFilterAnalytics: LoadRow<RefundFilterRow> {}
+
+pub async fn get_refund_filter_for_dimension<T>(
+    dimension: RefundDimensions,
+    merchant: &String,
+    time_range: &TimeRange,
+    pool: &T,
+) -> FiltersResult<Vec<RefundFilterRow>>
+where
+    T: AnalyticsDataSource + RefundFilterAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::Refund);
+
+    query_builder.add_select_column(dimension).switch()?;
+    time_range
+        .set_filter_clause(&mut query_builder)
+        .attach_printable("Error filtering time range")
+        .switch()?;
+
+    query_builder
+        .add_filter_clause("merchant_id", merchant)
+        .switch()?;
+
+    query_builder.set_distinct();
+
+    query_builder
+        .execute_query::<RefundFilterRow, _>(pool)
+        .await
+        .change_context(FiltersError::QueryBuildingError)?
+        .change_context(FiltersError::QueryExecutionFailure)
+}
+
+#[derive(Debug, serde::Serialize, Eq, PartialEq)]
+pub struct RefundFilterRow {
+    pub currency: Option<DBEnumWrapper<Currency>>,
+    pub refund_status: Option<DBEnumWrapper<RefundStatus>>,
+    pub connector: Option<String>,
+    pub refund_type: Option<DBEnumWrapper<RefundType>>,
+}
diff --git a/crates/router/src/analytics/refunds/metrics.rs b/crates/router/src/analytics/refunds/metrics.rs
new file mode 100644
index 000000000000..d4f509b4a1e3
--- /dev/null
+++ b/crates/router/src/analytics/refunds/metrics.rs
@@ -0,0 +1,126 @@
+use api_models::analytics::{
+    refunds::{
+        RefundDimensions, RefundFilters, RefundMetrics, RefundMetricsBucketIdentifier, RefundType,
+    },
+    Granularity, TimeRange,
+};
+use common_enums::enums as storage_enums;
+use time::PrimitiveDateTime;
+mod refund_count;
+mod refund_processed_amount;
+mod refund_success_count;
+mod refund_success_rate;
+use refund_count::RefundCount;
+use refund_processed_amount::RefundProcessedAmount;
+use refund_success_count::RefundSuccessCount;
+use refund_success_rate::RefundSuccessRate;
+
+use crate::analytics::{
+    query::{Aggregate, GroupByClause, ToSql},
+    types::{AnalyticsCollection, AnalyticsDataSource, DBEnumWrapper, LoadRow, MetricsResult},
+};
+
+#[derive(Debug, Eq, PartialEq)]
+pub struct RefundMetricRow {
+    pub currency: Option<DBEnumWrapper<storage_enums::Currency>>,
+    pub refund_status: Option<DBEnumWrapper<storage_enums::RefundStatus>>,
+    pub connector: Option<String>,
+    pub refund_type: Option<DBEnumWrapper<RefundType>>,
+    pub total: Option<bigdecimal::BigDecimal>,
+    pub count: Option<i64>,
+    pub start_bucket: Option<PrimitiveDateTime>,
+    pub end_bucket: Option<PrimitiveDateTime>,
+}
+
+pub trait RefundMetricAnalytics: LoadRow<RefundMetricRow> {}
+
+#[async_trait::async_trait]
+pub trait RefundMetric<T>
+where
+    T: AnalyticsDataSource + RefundMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[RefundDimensions],
+        merchant_id: &str,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(RefundMetricsBucketIdentifier, RefundMetricRow)>>;
+}
+
+#[async_trait::async_trait]
+impl<T> RefundMetric<T> for RefundMetrics
+where
+    T: AnalyticsDataSource + RefundMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[RefundDimensions],
+        merchant_id: &str,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(RefundMetricsBucketIdentifier, RefundMetricRow)>> {
+        match self {
+            Self::RefundSuccessRate => {
+                RefundSuccessRate::default()
+                    .load_metrics(
+                        dimensions,
+                        merchant_id,
+                        filters,
+                        granularity,
+                        time_range,
+                        pool,
+                    )
+                    .await
+            }
+            Self::RefundCount => {
+                RefundCount::default()
+                    .load_metrics(
+                        dimensions,
+                        merchant_id,
+                        filters,
+                        granularity,
+                        time_range,
+                        pool,
+                    )
+                    .await
+            }
+            Self::RefundSuccessCount => {
+                RefundSuccessCount::default()
+                    .load_metrics(
+                        dimensions,
+                        merchant_id,
+                        filters,
+                        granularity,
+                        time_range,
+                        pool,
+                    )
+                    .await
+            }
+            Self::RefundProcessedAmount => {
+                RefundProcessedAmount::default()
+                    .load_metrics(
+                        dimensions,
+                        merchant_id,
+                        filters,
+                        granularity,
+                        time_range,
+                        pool,
+                    )
+                    .await
+            }
+        }
+    }
+}
diff --git a/crates/router/src/analytics/refunds/metrics/refund_count.rs b/crates/router/src/analytics/refunds/metrics/refund_count.rs
new file mode 100644
index 000000000000..471327235073
--- /dev/null
+++ b/crates/router/src/analytics/refunds/metrics/refund_count.rs
@@ -0,0 +1,116 @@
+use api_models::analytics::{
+    refunds::{RefundDimensions, RefundFilters, RefundMetricsBucketIdentifier},
+    Granularity, TimeRange,
+};
+use common_utils::errors::ReportSwitchExt;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use super::RefundMetricRow;
+use crate::analytics::{
+    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql},
+    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+};
+
+#[derive(Default)]
+pub(super) struct RefundCount {}
+
+#[async_trait::async_trait]
+impl<T> super::RefundMetric<T> for RefundCount
+where
+    T: AnalyticsDataSource + super::RefundMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[RefundDimensions],
+        merchant_id: &str,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(RefundMetricsBucketIdentifier, RefundMetricRow)>> {
+        let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::Refund);
+
+        for dim in dimensions.iter() {
+            query_builder.add_select_column(dim).switch()?;
+        }
+
+        query_builder
+            .add_select_column(Aggregate::Count {
+                field: None,
+                alias: Some("count"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Min {
+                field: "created_at",
+                alias: Some("start_bucket"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Max {
+                field: "created_at",
+                alias: Some("end_bucket"),
+            })
+            .switch()?;
+
+        filters.set_filter_clause(&mut query_builder).switch()?;
+
+        query_builder
+            .add_filter_clause("merchant_id", merchant_id)
+            .switch()?;
+
+        time_range
+            .set_filter_clause(&mut query_builder)
+            .attach_printable("Error filtering time range")
+            .switch()?;
+
+        for dim in dimensions.iter() {
+            query_builder
+                .add_group_by_clause(dim)
+                .attach_printable("Error grouping by dimensions")
+                .switch()?;
+        }
+
+        if let Some(granularity) = granularity.as_ref() {
+            granularity
+                .set_group_by_clause(&mut query_builder)
+                .attach_printable("Error adding granularity")
+                .switch()?;
+        }
+
+        query_builder
+            .execute_query::<RefundMetricRow, _>(pool)
+            .await
+            .change_context(MetricsError::QueryBuildingError)?
+            .change_context(MetricsError::QueryExecutionFailure)?
+            .into_iter()
+            .map(|i| {
+                Ok((
+                    RefundMetricsBucketIdentifier::new(
+                        i.currency.as_ref().map(|i| i.0),
+                        i.refund_status.as_ref().map(|i| i.0),
+                        i.connector.clone(),
+                        i.refund_type.as_ref().map(|i| i.0.to_string()),
+                        TimeRange {
+                            start_time: match (granularity, i.start_bucket) {
+                                (Some(g), Some(st)) => g.clip_to_start(st)?,
+                                _ => time_range.start_time,
+                            },
+                            end_time: granularity.as_ref().map_or_else(
+                                || Ok(time_range.end_time),
+                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
+                            )?,
+                        },
+                    ),
+                    i,
+                ))
+            })
+            .collect::<error_stack::Result<Vec<_>, crate::analytics::query::PostProcessingError>>()
+            .change_context(MetricsError::PostProcessingFailure)
+    }
+}
diff --git a/crates/router/src/analytics/refunds/metrics/refund_processed_amount.rs b/crates/router/src/analytics/refunds/metrics/refund_processed_amount.rs
new file mode 100644
index 000000000000..c5f3a706aaef
--- /dev/null
+++ b/crates/router/src/analytics/refunds/metrics/refund_processed_amount.rs
@@ -0,0 +1,122 @@
+use api_models::analytics::{
+    refunds::{RefundDimensions, RefundFilters, RefundMetricsBucketIdentifier},
+    Granularity, TimeRange,
+};
+use common_enums::enums as storage_enums;
+use common_utils::errors::ReportSwitchExt;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use super::RefundMetricRow;
+use crate::analytics::{
+    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql},
+    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+};
+#[derive(Default)]
+pub(super) struct RefundProcessedAmount {}
+
+#[async_trait::async_trait]
+impl<T> super::RefundMetric<T> for RefundProcessedAmount
+where
+    T: AnalyticsDataSource + super::RefundMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[RefundDimensions],
+        merchant_id: &str,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(RefundMetricsBucketIdentifier, RefundMetricRow)>>
+    where
+        T: AnalyticsDataSource + super::RefundMetricAnalytics,
+    {
+        let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::Refund);
+
+        for dim in dimensions.iter() {
+            query_builder.add_select_column(dim).switch()?;
+        }
+
+        query_builder
+            .add_select_column(Aggregate::Sum {
+                field: "refund_amount",
+                alias: Some("total"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Min {
+                field: "created_at",
+                alias: Some("start_bucket"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Max {
+                field: "created_at",
+                alias: Some("end_bucket"),
+            })
+            .switch()?;
+
+        filters.set_filter_clause(&mut query_builder).switch()?;
+
+        query_builder
+            .add_filter_clause("merchant_id", merchant_id)
+            .switch()?;
+
+        time_range
+            .set_filter_clause(&mut query_builder)
+            .attach_printable("Error filtering time range")
+            .switch()?;
+
+        for dim in dimensions.iter() {
+            query_builder.add_group_by_clause(dim).switch()?;
+        }
+
+        if let Some(granularity) = granularity.as_ref() {
+            granularity
+                .set_group_by_clause(&mut query_builder)
+                .switch()?;
+        }
+
+        query_builder
+            .add_filter_clause(
+                RefundDimensions::RefundStatus,
+                storage_enums::RefundStatus::Success,
+            )
+            .switch()?;
+
+        query_builder
+            .execute_query::<RefundMetricRow, _>(pool)
+            .await
+            .change_context(MetricsError::QueryBuildingError)?
+            .change_context(MetricsError::QueryExecutionFailure)?
+            .into_iter()
+            .map(|i| {
+                Ok((
+                    RefundMetricsBucketIdentifier::new(
+                        i.currency.as_ref().map(|i| i.0),
+                        None,
+                        i.connector.clone(),
+                        i.refund_type.as_ref().map(|i| i.0.to_string()),
+                        TimeRange {
+                            start_time: match (granularity, i.start_bucket) {
+                                (Some(g), Some(st)) => g.clip_to_start(st)?,
+                                _ => time_range.start_time,
+                            },
+                            end_time: granularity.as_ref().map_or_else(
+                                || Ok(time_range.end_time),
+                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
+                            )?,
+                        },
+                    ),
+                    i,
+                ))
+            })
+            .collect::<error_stack::Result<Vec<_>, crate::analytics::query::PostProcessingError>>()
+            .change_context(MetricsError::PostProcessingFailure)
+    }
+}
diff --git a/crates/router/src/analytics/refunds/metrics/refund_success_count.rs b/crates/router/src/analytics/refunds/metrics/refund_success_count.rs
new file mode 100644
index 000000000000..0c8032908fd7
--- /dev/null
+++ b/crates/router/src/analytics/refunds/metrics/refund_success_count.rs
@@ -0,0 +1,122 @@
+use api_models::analytics::{
+    refunds::{RefundDimensions, RefundFilters, RefundMetricsBucketIdentifier},
+    Granularity, TimeRange,
+};
+use common_enums::enums as storage_enums;
+use common_utils::errors::ReportSwitchExt;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use super::RefundMetricRow;
+use crate::analytics::{
+    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql},
+    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+};
+
+#[derive(Default)]
+pub(super) struct RefundSuccessCount {}
+
+#[async_trait::async_trait]
+impl<T> super::RefundMetric<T> for RefundSuccessCount
+where
+    T: AnalyticsDataSource + super::RefundMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[RefundDimensions],
+        merchant_id: &str,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(RefundMetricsBucketIdentifier, RefundMetricRow)>>
+    where
+        T: AnalyticsDataSource + super::RefundMetricAnalytics,
+    {
+        let mut query_builder = QueryBuilder::new(AnalyticsCollection::Refund);
+
+        for dim in dimensions.iter() {
+            query_builder.add_select_column(dim).switch()?;
+        }
+
+        query_builder
+            .add_select_column(Aggregate::Count {
+                field: None,
+                alias: Some("count"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Min {
+                field: "created_at",
+                alias: Some("start_bucket"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Max {
+                field: "created_at",
+                alias: Some("end_bucket"),
+            })
+            .switch()?;
+
+        filters.set_filter_clause(&mut query_builder).switch()?;
+
+        query_builder
+            .add_filter_clause("merchant_id", merchant_id)
+            .switch()?;
+
+        time_range.set_filter_clause(&mut query_builder).switch()?;
+
+        for dim in dimensions.iter() {
+            query_builder.add_group_by_clause(dim).switch()?;
+        }
+
+        if let Some(granularity) = granularity.as_ref() {
+            granularity
+                .set_group_by_clause(&mut query_builder)
+                .switch()?;
+        }
+
+        query_builder
+            .add_filter_clause(
+                RefundDimensions::RefundStatus,
+                storage_enums::RefundStatus::Success,
+            )
+            .switch()?;
+        query_builder
+            .execute_query::<RefundMetricRow, _>(pool)
+            .await
+            .change_context(MetricsError::QueryBuildingError)?
+            .change_context(MetricsError::QueryExecutionFailure)?
+            .into_iter()
+            .map(|i| {
+                Ok((
+                    RefundMetricsBucketIdentifier::new(
+                        i.currency.as_ref().map(|i| i.0),
+                        None,
+                        i.connector.clone(),
+                        i.refund_type.as_ref().map(|i| i.0.to_string()),
+                        TimeRange {
+                            start_time: match (granularity, i.start_bucket) {
+                                (Some(g), Some(st)) => g.clip_to_start(st)?,
+                                _ => time_range.start_time,
+                            },
+                            end_time: granularity.as_ref().map_or_else(
+                                || Ok(time_range.end_time),
+                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
+                            )?,
+                        },
+                    ),
+                    i,
+                ))
+            })
+            .collect::<error_stack::Result<
+                Vec<(RefundMetricsBucketIdentifier, RefundMetricRow)>,
+                crate::analytics::query::PostProcessingError,
+            >>()
+            .change_context(MetricsError::PostProcessingFailure)
+    }
+}
diff --git a/crates/router/src/analytics/refunds/metrics/refund_success_rate.rs b/crates/router/src/analytics/refunds/metrics/refund_success_rate.rs
new file mode 100644
index 000000000000..42f9ccf8d3c0
--- /dev/null
+++ b/crates/router/src/analytics/refunds/metrics/refund_success_rate.rs
@@ -0,0 +1,117 @@
+use api_models::analytics::{
+    refunds::{RefundDimensions, RefundFilters, RefundMetricsBucketIdentifier},
+    Granularity, TimeRange,
+};
+use common_utils::errors::ReportSwitchExt;
+use error_stack::ResultExt;
+use time::PrimitiveDateTime;
+
+use super::RefundMetricRow;
+use crate::analytics::{
+    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql},
+    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+};
+#[derive(Default)]
+pub(super) struct RefundSuccessRate {}
+
+#[async_trait::async_trait]
+impl<T> super::RefundMetric<T> for RefundSuccessRate
+where
+    T: AnalyticsDataSource + super::RefundMetricAnalytics,
+    PrimitiveDateTime: ToSql<T>,
+    AnalyticsCollection: ToSql<T>,
+    Granularity: GroupByClause<T>,
+    Aggregate<&'static str>: ToSql<T>,
+{
+    async fn load_metrics(
+        &self,
+        dimensions: &[RefundDimensions],
+        merchant_id: &str,
+        filters: &RefundFilters,
+        granularity: &Option<Granularity>,
+        time_range: &TimeRange,
+        pool: &T,
+    ) -> MetricsResult<Vec<(RefundMetricsBucketIdentifier, RefundMetricRow)>>
+    where
+        T: AnalyticsDataSource + super::RefundMetricAnalytics,
+    {
+        let mut query_builder = QueryBuilder::new(AnalyticsCollection::Refund);
+        let mut dimensions = dimensions.to_vec();
+
+        dimensions.push(RefundDimensions::RefundStatus);
+
+        for dim in dimensions.iter() {
+            query_builder.add_select_column(dim).switch()?;
+        }
+
+        query_builder
+            .add_select_column(Aggregate::Count {
+                field: None,
+                alias: Some("count"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Min {
+                field: "created_at",
+                alias: Some("start_bucket"),
+            })
+            .switch()?;
+        query_builder
+            .add_select_column(Aggregate::Max {
+                field: "created_at",
+                alias: Some("end_bucket"),
+            })
+            .switch()?;
+
+        filters.set_filter_clause(&mut query_builder).switch()?;
+
+        query_builder
+            .add_filter_clause("merchant_id", merchant_id)
+            .switch()?;
+
+        time_range.set_filter_clause(&mut query_builder).switch()?;
+
+        for dim in dimensions.iter() {
+            query_builder.add_group_by_clause(dim).switch()?;
+        }
+
+        if let Some(granularity) = granularity.as_ref() {
+            granularity
+                .set_group_by_clause(&mut query_builder)
+                .switch()?;
+        }
+
+        query_builder
+            .execute_query::<RefundMetricRow, _>(pool)
+            .await
+            .change_context(MetricsError::QueryBuildingError)?
+            .change_context(MetricsError::QueryExecutionFailure)?
+            .into_iter()
+            .map(|i| {
+                Ok((
+                    RefundMetricsBucketIdentifier::new(
+                        i.currency.as_ref().map(|i| i.0),
+                        None,
+                        i.connector.clone(),
+                        i.refund_type.as_ref().map(|i| i.0.to_string()),
+                        TimeRange {
+                            start_time: match (granularity, i.start_bucket) {
+                                (Some(g), Some(st)) => g.clip_to_start(st)?,
+                                _ => time_range.start_time,
+                            },
+                            end_time: granularity.as_ref().map_or_else(
+                                || Ok(time_range.end_time),
+                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
+                            )?,
+                        },
+                    ),
+                    i,
+                ))
+            })
+            .collect::<error_stack::Result<
+                Vec<(RefundMetricsBucketIdentifier, RefundMetricRow)>,
+                crate::analytics::query::PostProcessingError,
+            >>()
+            .change_context(MetricsError::PostProcessingFailure)
+    }
+}
diff --git a/crates/router/src/analytics/refunds/types.rs b/crates/router/src/analytics/refunds/types.rs
new file mode 100644
index 000000000000..fbfd69972671
--- /dev/null
+++ b/crates/router/src/analytics/refunds/types.rs
@@ -0,0 +1,41 @@
+use api_models::analytics::refunds::{RefundDimensions, RefundFilters};
+use error_stack::ResultExt;
+
+use crate::analytics::{
+    query::{QueryBuilder, QueryFilter, QueryResult, ToSql},
+    types::{AnalyticsCollection, AnalyticsDataSource},
+};
+
+impl<T> QueryFilter<T> for RefundFilters
+where
+    T: AnalyticsDataSource,
+    AnalyticsCollection: ToSql<T>,
+{
+    fn set_filter_clause(&self, builder: &mut QueryBuilder<T>) -> QueryResult<()> {
+        if !self.currency.is_empty() {
+            builder
+                .add_filter_in_range_clause(RefundDimensions::Currency, &self.currency)
+                .attach_printable("Error adding currency filter")?;
+        }
+
+        if !self.refund_status.is_empty() {
+            builder
+                .add_filter_in_range_clause(RefundDimensions::RefundStatus, &self.refund_status)
+                .attach_printable("Error adding refund status filter")?;
+        }
+
+        if !self.connector.is_empty() {
+            builder
+                .add_filter_in_range_clause(RefundDimensions::Connector, &self.connector)
+                .attach_printable("Error adding connector filter")?;
+        }
+
+        if !self.refund_type.is_empty() {
+            builder
+                .add_filter_in_range_clause(RefundDimensions::RefundType, &self.refund_type)
+                .attach_printable("Error adding auth type filter")?;
+        }
+
+        Ok(())
+    }
+}
diff --git a/crates/router/src/analytics/routes.rs b/crates/router/src/analytics/routes.rs
new file mode 100644
index 000000000000..298ec61ec903
--- /dev/null
+++ b/crates/router/src/analytics/routes.rs
@@ -0,0 +1,145 @@
+use actix_web::{web, Responder, Scope};
+use api_models::analytics::{
+    GetPaymentFiltersRequest, GetPaymentMetricRequest, GetRefundFilterRequest,
+    GetRefundMetricRequest,
+};
+use router_env::AnalyticsFlow;
+
+use super::{core::*, payments, refunds, types::AnalyticsDomain};
+use crate::{
+    core::api_locking,
+    services::{api, authentication as auth, authentication::AuthenticationData},
+    AppState,
+};
+
+pub struct Analytics;
+
+impl Analytics {
+    pub fn server(state: AppState) -> Scope {
+        let route = web::scope("/analytics/v1").app_data(web::Data::new(state));
+        route
+            .service(web::resource("metrics/payments").route(web::post().to(get_payment_metrics)))
+            .service(web::resource("metrics/refunds").route(web::post().to(get_refunds_metrics)))
+            .service(web::resource("filters/payments").route(web::post().to(get_payment_filters)))
+            .service(web::resource("filters/refunds").route(web::post().to(get_refund_filters)))
+            .service(web::resource("{domain}/info").route(web::get().to(get_info)))
+    }
+}
+
+pub async fn get_info(
+    state: web::Data<AppState>,
+    req: actix_web::HttpRequest,
+    domain: actix_web::web::Path<AnalyticsDomain>,
+) -> impl Responder {
+    let flow = AnalyticsFlow::GetInfo;
+    api::server_wrap(
+        flow,
+        state,
+        &req,
+        domain.into_inner(),
+        |_, _, domain| get_domain_info(domain),
+        &auth::NoAuth,
+        api_locking::LockAction::NotApplicable,
+    )
+    .await
+}
+
+/// # Panics
+///
+/// Panics if `json_payload` array does not contain one `GetPaymentMetricRequest` element.
+pub async fn get_payment_metrics(
+    state: web::Data<AppState>,
+    req: actix_web::HttpRequest,
+    json_payload: web::Json<[GetPaymentMetricRequest; 1]>,
+) -> impl Responder {
+    // safety: This shouldn't panic owing to the data type
+    #[allow(clippy::expect_used)]
+    let payload = json_payload
+        .into_inner()
+        .to_vec()
+        .pop()
+        .expect("Couldn't get GetPaymentMetricRequest");
+    let flow = AnalyticsFlow::GetPaymentMetrics;
+    api::server_wrap(
+        flow,
+        state,
+        &req,
+        payload,
+        |state, auth: AuthenticationData, req| {
+            payments::get_metrics(state.pool.clone(), auth.merchant_account, req)
+        },
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+        api_locking::LockAction::NotApplicable,
+    )
+    .await
+}
+
+/// # Panics
+///
+/// Panics if `json_payload` array does not contain one `GetRefundMetricRequest` element.
+pub async fn get_refunds_metrics(
+    state: web::Data<AppState>,
+    req: actix_web::HttpRequest,
+    json_payload: web::Json<[GetRefundMetricRequest; 1]>,
+) -> impl Responder {
+    #[allow(clippy::expect_used)]
+    // safety: This shouldn't panic owing to the data type
+    let payload = json_payload
+        .into_inner()
+        .to_vec()
+        .pop()
+        .expect("Couldn't get GetRefundMetricRequest");
+    let flow = AnalyticsFlow::GetRefundsMetrics;
+    api::server_wrap(
+        flow,
+        state,
+        &req,
+        payload,
+        |state, auth: AuthenticationData, req| {
+            refunds::get_metrics(state.pool.clone(), auth.merchant_account, req)
+        },
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+        api_locking::LockAction::NotApplicable,
+    )
+    .await
+}
+
+pub async fn get_payment_filters(
+    state: web::Data<AppState>,
+    req: actix_web::HttpRequest,
+    json_payload: web::Json<GetPaymentFiltersRequest>,
+) -> impl Responder {
+    let flow = AnalyticsFlow::GetPaymentFilters;
+    api::server_wrap(
+        flow,
+        state,
+        &req,
+        json_payload.into_inner(),
+        |state, auth: AuthenticationData, req| {
+            payment_filters_core(state.pool.clone(), req, auth.merchant_account)
+        },
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+        api_locking::LockAction::NotApplicable,
+    )
+    .await
+}
+
+pub async fn get_refund_filters(
+    state: web::Data<AppState>,
+    req: actix_web::HttpRequest,
+    json_payload: web::Json<GetRefundFilterRequest>,
+) -> impl Responder {
+    let flow = AnalyticsFlow::GetRefundFilters;
+    api::server_wrap(
+        flow,
+        state,
+        &req,
+        json_payload.into_inner(),
+        |state, auth: AuthenticationData, req: GetRefundFilterRequest| {
+            refund_filter_core(state.pool.clone(), req, auth.merchant_account)
+        },
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+        api_locking::LockAction::NotApplicable,
+    )
+    .await
+}
diff --git a/crates/router/src/analytics/sqlx.rs b/crates/router/src/analytics/sqlx.rs
new file mode 100644
index 000000000000..b88a2065f0b0
--- /dev/null
+++ b/crates/router/src/analytics/sqlx.rs
@@ -0,0 +1,401 @@
+use std::{fmt::Display, str::FromStr};
+
+use api_models::analytics::refunds::RefundType;
+use common_enums::enums::{
+    AttemptStatus, AuthenticationType, Currency, PaymentMethod, RefundStatus,
+};
+use common_utils::errors::{CustomResult, ParsingError};
+use error_stack::{IntoReport, ResultExt};
+#[cfg(feature = "kms")]
+use external_services::{kms, kms::decrypt::KmsDecrypt};
+#[cfg(not(feature = "kms"))]
+use masking::PeekInterface;
+use sqlx::{
+    postgres::{PgArgumentBuffer, PgPoolOptions, PgRow, PgTypeInfo, PgValueRef},
+    Decode, Encode,
+    Error::ColumnNotFound,
+    FromRow, Pool, Postgres, Row,
+};
+use time::PrimitiveDateTime;
+
+use super::{
+    query::{Aggregate, ToSql},
+    types::{
+        AnalyticsCollection, AnalyticsDataSource, DBEnumWrapper, LoadRow, QueryExecutionError,
+    },
+};
+use crate::configs::settings::Database;
+
+#[derive(Debug, Clone)]
+pub struct SqlxClient {
+    pool: Pool<Postgres>,
+}
+
+impl Default for SqlxClient {
+    fn default() -> Self {
+        let database_url = format!(
+            "postgres://{}:{}@{}:{}/{}",
+            "db_user", "db_pass", "localhost", 5432, "hyperswitch_db"
+        );
+        Self {
+            #[allow(clippy::expect_used)]
+            pool: PgPoolOptions::new()
+                .connect_lazy(&database_url)
+                .expect("SQLX Pool Creation failed"),
+        }
+    }
+}
+
+impl SqlxClient {
+    pub async fn from_conf(
+        conf: &Database,
+        #[cfg(feature = "kms")] kms_client: &kms::KmsClient,
+    ) -> Self {
+        #[cfg(feature = "kms")]
+        #[allow(clippy::expect_used)]
+        let password = conf
+            .password
+            .decrypt_inner(kms_client)
+            .await
+            .expect("Failed to KMS decrypt database password");
+
+        #[cfg(not(feature = "kms"))]
+        let password = &conf.password.peek();
+        let database_url = format!(
+            "postgres://{}:{}@{}:{}/{}",
+            conf.username, password, conf.host, conf.port, conf.dbname
+        );
+        #[allow(clippy::expect_used)]
+        let pool = PgPoolOptions::new()
+            .max_connections(conf.pool_size)
+            .acquire_timeout(std::time::Duration::from_secs(conf.connection_timeout))
+            .connect_lazy(&database_url)
+            .expect("SQLX Pool Creation failed");
+        Self { pool }
+    }
+}
+
+pub trait DbType {
+    fn name() -> &'static str;
+}
+
+macro_rules! db_type {
+    ($a: ident, $str: tt) => {
+        impl DbType for $a {
+            fn name() -> &'static str {
+                stringify!($str)
+            }
+        }
+    };
+    ($a:ident) => {
+        impl DbType for $a {
+            fn name() -> &'static str {
+                stringify!($a)
+            }
+        }
+    };
+}
+
+db_type!(Currency);
+db_type!(AuthenticationType);
+db_type!(AttemptStatus);
+db_type!(PaymentMethod, TEXT);
+db_type!(RefundStatus);
+db_type!(RefundType);
+
+impl<'q, Type> Encode<'q, Postgres> for DBEnumWrapper<Type>
+where
+    Type: DbType + FromStr + Display,
+{
+    fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> sqlx::encode::IsNull {
+        self.0.to_string().encode(buf)
+    }
+    fn size_hint(&self) -> usize {
+        self.0.to_string().size_hint()
+    }
+}
+
+impl<'r, Type> Decode<'r, Postgres> for DBEnumWrapper<Type>
+where
+    Type: DbType + FromStr + Display,
+{
+    fn decode(
+        value: PgValueRef<'r>,
+    ) -> Result<Self, Box<dyn std::error::Error + 'static + Send + Sync>> {
+        let str_value = <&'r str as Decode<'r, Postgres>>::decode(value)?;
+        Type::from_str(str_value).map(DBEnumWrapper).or(Err(format!(
+            "invalid value {:?} for enum {}",
+            str_value,
+            Type::name()
+        )
+        .into()))
+    }
+}
+
+impl<Type> sqlx::Type<Postgres> for DBEnumWrapper<Type>
+where
+    Type: DbType + FromStr + Display,
+{
+    fn type_info() -> PgTypeInfo {
+        PgTypeInfo::with_name(Type::name())
+    }
+}
+
+impl<T> LoadRow<T> for SqlxClient
+where
+    for<'a> T: FromRow<'a, PgRow>,
+{
+    fn load_row(row: PgRow) -> CustomResult<T, QueryExecutionError> {
+        T::from_row(&row)
+            .into_report()
+            .change_context(QueryExecutionError::RowExtractionFailure)
+    }
+}
+
+impl super::payments::filters::PaymentFilterAnalytics for SqlxClient {}
+impl super::payments::metrics::PaymentMetricAnalytics for SqlxClient {}
+impl super::refunds::metrics::RefundMetricAnalytics for SqlxClient {}
+impl super::refunds::filters::RefundFilterAnalytics for SqlxClient {}
+
+#[async_trait::async_trait]
+impl AnalyticsDataSource for SqlxClient {
+    type Row = PgRow;
+
+    async fn load_results<T>(&self, query: &str) -> CustomResult<Vec<T>, QueryExecutionError>
+    where
+        Self: LoadRow<T>,
+    {
+        sqlx::query(&format!("{query};"))
+            .fetch_all(&self.pool)
+            .await
+            .into_report()
+            .change_context(QueryExecutionError::DatabaseError)
+            .attach_printable_lazy(|| format!("Failed to run query {query}"))?
+            .into_iter()
+            .map(Self::load_row)
+            .collect::<Result<Vec<_>, _>>()
+            .change_context(QueryExecutionError::RowExtractionFailure)
+    }
+}
+
+impl<'a> FromRow<'a, PgRow> for super::refunds::metrics::RefundMetricRow {
+    fn from_row(row: &'a PgRow) -> sqlx::Result<Self> {
+        let currency: Option<DBEnumWrapper<Currency>> =
+            row.try_get("currency").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let refund_status: Option<DBEnumWrapper<RefundStatus>> =
+            row.try_get("refund_status").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let connector: Option<String> = row.try_get("connector").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+        let refund_type: Option<DBEnumWrapper<RefundType>> =
+            row.try_get("refund_type").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let total: Option<bigdecimal::BigDecimal> = row.try_get("total").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+        let count: Option<i64> = row.try_get("count").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+
+        let start_bucket: Option<PrimitiveDateTime> = row
+            .try_get::<Option<PrimitiveDateTime>, _>("start_bucket")?
+            .and_then(|dt| dt.replace_millisecond(0).ok());
+        let end_bucket: Option<PrimitiveDateTime> = row
+            .try_get::<Option<PrimitiveDateTime>, _>("end_bucket")?
+            .and_then(|dt| dt.replace_millisecond(0).ok());
+        Ok(Self {
+            currency,
+            refund_status,
+            connector,
+            refund_type,
+            total,
+            count,
+            start_bucket,
+            end_bucket,
+        })
+    }
+}
+
+impl<'a> FromRow<'a, PgRow> for super::payments::metrics::PaymentMetricRow {
+    fn from_row(row: &'a PgRow) -> sqlx::Result<Self> {
+        let currency: Option<DBEnumWrapper<Currency>> =
+            row.try_get("currency").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let status: Option<DBEnumWrapper<AttemptStatus>> =
+            row.try_get("status").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let connector: Option<String> = row.try_get("connector").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+        let authentication_type: Option<DBEnumWrapper<AuthenticationType>> =
+            row.try_get("authentication_type").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let payment_method: Option<String> =
+            row.try_get("payment_method").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let total: Option<bigdecimal::BigDecimal> = row.try_get("total").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+        let count: Option<i64> = row.try_get("count").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+
+        let start_bucket: Option<PrimitiveDateTime> = row
+            .try_get::<Option<PrimitiveDateTime>, _>("start_bucket")?
+            .and_then(|dt| dt.replace_millisecond(0).ok());
+        let end_bucket: Option<PrimitiveDateTime> = row
+            .try_get::<Option<PrimitiveDateTime>, _>("end_bucket")?
+            .and_then(|dt| dt.replace_millisecond(0).ok());
+        Ok(Self {
+            currency,
+            status,
+            connector,
+            authentication_type,
+            payment_method,
+            total,
+            count,
+            start_bucket,
+            end_bucket,
+        })
+    }
+}
+
+impl<'a> FromRow<'a, PgRow> for super::payments::filters::FilterRow {
+    fn from_row(row: &'a PgRow) -> sqlx::Result<Self> {
+        let currency: Option<DBEnumWrapper<Currency>> =
+            row.try_get("currency").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let status: Option<DBEnumWrapper<AttemptStatus>> =
+            row.try_get("status").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let connector: Option<String> = row.try_get("connector").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+        let authentication_type: Option<DBEnumWrapper<AuthenticationType>> =
+            row.try_get("authentication_type").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let payment_method: Option<String> =
+            row.try_get("payment_method").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        Ok(Self {
+            currency,
+            status,
+            connector,
+            authentication_type,
+            payment_method,
+        })
+    }
+}
+
+impl<'a> FromRow<'a, PgRow> for super::refunds::filters::RefundFilterRow {
+    fn from_row(row: &'a PgRow) -> sqlx::Result<Self> {
+        let currency: Option<DBEnumWrapper<Currency>> =
+            row.try_get("currency").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let refund_status: Option<DBEnumWrapper<RefundStatus>> =
+            row.try_get("refund_status").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        let connector: Option<String> = row.try_get("connector").or_else(|e| match e {
+            ColumnNotFound(_) => Ok(Default::default()),
+            e => Err(e),
+        })?;
+        let refund_type: Option<DBEnumWrapper<RefundType>> =
+            row.try_get("refund_type").or_else(|e| match e {
+                ColumnNotFound(_) => Ok(Default::default()),
+                e => Err(e),
+            })?;
+        Ok(Self {
+            currency,
+            refund_status,
+            connector,
+            refund_type,
+        })
+    }
+}
+
+impl ToSql<SqlxClient> for PrimitiveDateTime {
+    fn to_sql(&self) -> error_stack::Result<String, ParsingError> {
+        Ok(self.to_string())
+    }
+}
+
+impl ToSql<SqlxClient> for AnalyticsCollection {
+    fn to_sql(&self) -> error_stack::Result<String, ParsingError> {
+        match self {
+            Self::Payment => Ok("payment_attempt".to_string()),
+            Self::Refund => Ok("refund".to_string()),
+        }
+    }
+}
+
+impl<T> ToSql<SqlxClient> for Aggregate<T>
+where
+    T: ToSql<SqlxClient>,
+{
+    fn to_sql(&self) -> error_stack::Result<String, ParsingError> {
+        Ok(match self {
+            Self::Count { field: _, alias } => {
+                format!(
+                    "count(*){}",
+                    alias.map_or_else(|| "".to_owned(), |alias| format!(" as {}", alias))
+                )
+            }
+            Self::Sum { field, alias } => {
+                format!(
+                    "sum({}){}",
+                    field.to_sql().attach_printable("Failed to sum aggregate")?,
+                    alias.map_or_else(|| "".to_owned(), |alias| format!(" as {}", alias))
+                )
+            }
+            Self::Min { field, alias } => {
+                format!(
+                    "min({}){}",
+                    field.to_sql().attach_printable("Failed to min aggregate")?,
+                    alias.map_or_else(|| "".to_owned(), |alias| format!(" as {}", alias))
+                )
+            }
+            Self::Max { field, alias } => {
+                format!(
+                    "max({}){}",
+                    field.to_sql().attach_printable("Failed to max aggregate")?,
+                    alias.map_or_else(|| "".to_owned(), |alias| format!(" as {}", alias))
+                )
+            }
+        })
+    }
+}
diff --git a/crates/router/src/analytics/types.rs b/crates/router/src/analytics/types.rs
new file mode 100644
index 000000000000..fe20e812a9b8
--- /dev/null
+++ b/crates/router/src/analytics/types.rs
@@ -0,0 +1,119 @@
+use std::{fmt::Display, str::FromStr};
+
+use common_utils::{
+    errors::{CustomResult, ErrorSwitch, ParsingError},
+    events::ApiEventMetric,
+};
+use error_stack::{report, Report, ResultExt};
+
+use super::query::QueryBuildingError;
+
+#[derive(serde::Deserialize, Debug, masking::Serialize)]
+#[serde(rename_all = "snake_case")]
+pub enum AnalyticsDomain {
+    Payments,
+    Refunds,
+}
+
+impl ApiEventMetric for AnalyticsDomain {}
+
+#[derive(Debug, strum::AsRefStr, strum::Display, Clone, Copy)]
+pub enum AnalyticsCollection {
+    Payment,
+    Refund,
+}
+
+#[derive(Debug, serde::Serialize, serde::Deserialize, Eq, PartialEq)]
+#[serde(transparent)]
+pub struct DBEnumWrapper<T: FromStr + Display>(pub T);
+
+impl<T: FromStr + Display> AsRef<T> for DBEnumWrapper<T> {
+    fn as_ref(&self) -> &T {
+        &self.0
+    }
+}
+
+impl<T> FromStr for DBEnumWrapper<T>
+where
+    T: FromStr + Display,
+{
+    type Err = Report<ParsingError>;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        T::from_str(s)
+            .map_err(|_er| report!(ParsingError::EnumParseFailure(std::any::type_name::<T>())))
+            .map(DBEnumWrapper)
+            .attach_printable_lazy(|| format!("raw_value: {s}"))
+    }
+}
+
+// Analytics Framework
+
+pub trait RefundAnalytics {}
+
+#[async_trait::async_trait]
+pub trait AnalyticsDataSource
+where
+    Self: Sized + Sync + Send,
+{
+    type Row;
+    async fn load_results<T>(&self, query: &str) -> CustomResult<Vec<T>, QueryExecutionError>
+    where
+        Self: LoadRow<T>;
+}
+
+pub trait LoadRow<T>
+where
+    Self: AnalyticsDataSource,
+    T: Sized,
+{
+    fn load_row(row: Self::Row) -> CustomResult<T, QueryExecutionError>;
+}
+
+#[derive(thiserror::Error, Debug)]
+pub enum MetricsError {
+    #[error("Error building query")]
+    QueryBuildingError,
+    #[error("Error running Query")]
+    QueryExecutionFailure,
+    #[error("Error processing query results")]
+    PostProcessingFailure,
+    #[allow(dead_code)]
+    #[error("Not Implemented")]
+    NotImplemented,
+}
+
+#[derive(Debug, thiserror::Error)]
+pub enum QueryExecutionError {
+    #[error("Failed to extract domain rows")]
+    RowExtractionFailure,
+    #[error("Database error")]
+    DatabaseError,
+}
+
+pub type MetricsResult<T> = CustomResult<T, MetricsError>;
+
+impl ErrorSwitch<MetricsError> for QueryBuildingError {
+    fn switch(&self) -> MetricsError {
+        MetricsError::QueryBuildingError
+    }
+}
+
+pub type FiltersResult<T> = CustomResult<T, FiltersError>;
+
+#[derive(thiserror::Error, Debug)]
+pub enum FiltersError {
+    #[error("Error building query")]
+    QueryBuildingError,
+    #[error("Error running Query")]
+    QueryExecutionFailure,
+    #[allow(dead_code)]
+    #[error("Not Implemented")]
+    NotImplemented,
+}
+
+impl ErrorSwitch<FiltersError> for QueryBuildingError {
+    fn switch(&self) -> FiltersError {
+        FiltersError::QueryBuildingError
+    }
+}
diff --git a/crates/router/src/analytics/utils.rs b/crates/router/src/analytics/utils.rs
new file mode 100644
index 000000000000..f7e6ea69dc37
--- /dev/null
+++ b/crates/router/src/analytics/utils.rs
@@ -0,0 +1,22 @@
+use api_models::analytics::{
+    payments::{PaymentDimensions, PaymentMetrics},
+    refunds::{RefundDimensions, RefundMetrics},
+    NameDescription,
+};
+use strum::IntoEnumIterator;
+
+pub fn get_payment_dimensions() -> Vec<NameDescription> {
+    PaymentDimensions::iter().map(Into::into).collect()
+}
+
+pub fn get_refund_dimensions() -> Vec<NameDescription> {
+    RefundDimensions::iter().map(Into::into).collect()
+}
+
+pub fn get_payment_metrics_info() -> Vec<NameDescription> {
+    PaymentMetrics::iter().map(Into::into).collect()
+}
+
+pub fn get_refund_metrics_info() -> Vec<NameDescription> {
+    RefundMetrics::iter().map(Into::into).collect()
+}
diff --git a/crates/router/src/bin/router.rs b/crates/router/src/bin/router.rs
index cb3a8d83b031..beb2869f998c 100644
--- a/crates/router/src/bin/router.rs
+++ b/crates/router/src/bin/router.rs
@@ -4,7 +4,7 @@ use router::{
     logger,
 };
 
-#[actix_web::main]
+#[tokio::main]
 async fn main() -> ApplicationResult<()> {
     // get commandline config before initializing config
     let cmd_line = <CmdLineConf as clap::Parser>::parse();
@@ -43,7 +43,7 @@ async fn main() -> ApplicationResult<()> {
     logger::info!("Application started [{:?}] [{:?}]", conf.server, conf.log);
 
     #[allow(clippy::expect_used)]
-    let server = router::start_server(conf)
+    let server = Box::pin(router::start_server(conf))
         .await
         .expect("Failed to create the server");
     let _ = server.await;
diff --git a/crates/router/src/bin/scheduler.rs b/crates/router/src/bin/scheduler.rs
index 09f23bc3b2f3..4c19408582bc 100644
--- a/crates/router/src/bin/scheduler.rs
+++ b/crates/router/src/bin/scheduler.rs
@@ -40,7 +40,12 @@ async fn main() -> CustomResult<(), ProcessTrackerError> {
     );
     // channel for listening to redis disconnect events
     let (redis_shutdown_signal_tx, redis_shutdown_signal_rx) = oneshot::channel();
-    let state = routes::AppState::new(conf, redis_shutdown_signal_tx, api_client).await;
+    let state = Box::pin(routes::AppState::new(
+        conf,
+        redis_shutdown_signal_tx,
+        api_client,
+    ))
+    .await;
     // channel to shutdown scheduler gracefully
     let (tx, rx) = mpsc::channel(1);
     tokio::spawn(router::receiver_for_error(
diff --git a/crates/router/src/compatibility/stripe/payment_intents.rs b/crates/router/src/compatibility/stripe/payment_intents.rs
index 1076dfe410fc..c237f21dde66 100644
--- a/crates/router/src/compatibility/stripe/payment_intents.rs
+++ b/crates/router/src/compatibility/stripe/payment_intents.rs
@@ -9,7 +9,7 @@ use crate::{
     core::{api_locking::GetLockingInput, payment_methods::Oss, payments},
     routes,
     services::{api, authentication as auth},
-    types::api::{self as api_types},
+    types::api as api_types,
 };
 
 #[instrument(skip_all, fields(flow = ?Flow::PaymentsCreate))]
@@ -50,6 +50,7 @@ pub async fn payment_intents_create(
         &req,
         create_payment_req,
         |state, auth, req| {
+            let eligible_connectors = req.connector.clone();
             payments::payments_core::<api_types::Authorize, api_types::PaymentsResponse, _, _, _,Oss>(
                 state,
                 auth.merchant_account,
@@ -58,6 +59,7 @@ pub async fn payment_intents_create(
                 req,
                 api::AuthFlow::Merchant,
                 payments::CallConnectorAction::Trigger,
+                eligible_connectors,
                 api_types::HeaderPayload::default(),
             )
         },
@@ -117,6 +119,7 @@ pub async fn payment_intents_retrieve(
                 payload,
                 auth_flow,
                 payments::CallConnectorAction::Trigger,
+                None,
                 api_types::HeaderPayload::default(),
             )
         },
@@ -180,6 +183,7 @@ pub async fn payment_intents_retrieve_with_gateway_creds(
                 req,
                 api::AuthFlow::Merchant,
                 payments::CallConnectorAction::Trigger,
+                    None,
                 api_types::HeaderPayload::default(),
             )
         },
@@ -236,6 +240,7 @@ pub async fn payment_intents_update(
         &req,
         payload,
         |state, auth, req| {
+            let eligible_connectors = req.connector.clone();
             payments::payments_core::<api_types::Authorize, api_types::PaymentsResponse, _, _, _,Oss>(
                 state,
                 auth.merchant_account,
@@ -244,6 +249,7 @@ pub async fn payment_intents_update(
                 req,
                 auth_flow,
                 payments::CallConnectorAction::Trigger,
+                eligible_connectors,
                 api_types::HeaderPayload::default(),
             )
         },
@@ -302,6 +308,7 @@ pub async fn payment_intents_confirm(
         &req,
         payload,
         |state, auth, req| {
+            let eligible_connectors = req.connector.clone();
             payments::payments_core::<api_types::Authorize, api_types::PaymentsResponse, _, _, _,Oss>(
                 state,
                 auth.merchant_account,
@@ -310,6 +317,7 @@ pub async fn payment_intents_confirm(
                 req,
                 auth_flow,
                 payments::CallConnectorAction::Trigger,
+                eligible_connectors,
                 api_types::HeaderPayload::default(),
             )
         },
@@ -366,6 +374,7 @@ pub async fn payment_intents_capture(
                 payload,
                 api::AuthFlow::Merchant,
                 payments::CallConnectorAction::Trigger,
+                    None,
                 api_types::HeaderPayload::default(),
             )
         },
@@ -426,6 +435,7 @@ pub async fn payment_intents_cancel(
                 req,
                 auth_flow,
                 payments::CallConnectorAction::Trigger,
+                None,
                 api_types::HeaderPayload::default(),
             )
         },
diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs
index 1cda32ffcca9..c713011b80c8 100644
--- a/crates/router/src/compatibility/stripe/payment_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs
@@ -281,7 +281,19 @@ impl TryFrom<StripePaymentIntentRequest> for payments::PaymentsRequest {
             });
 
         let routing = routable_connector
-            .map(crate::types::api::RoutingAlgorithm::Single)
+            .map(|connector| {
+                api_models::routing::RoutingAlgorithm::Single(Box::new(
+                    api_models::routing::RoutableConnectorChoice {
+                        #[cfg(feature = "backwards_compatibility")]
+                        choice_kind: api_models::routing::RoutableChoiceKind::FullStruct,
+                        connector,
+                        #[cfg(feature = "connector_choice_mca_id")]
+                        merchant_connector_id: None,
+                        #[cfg(not(feature = "connector_choice_mca_id"))]
+                        sub_label: None,
+                    },
+                ))
+            })
             .map(|r| {
                 serde_json::to_value(r)
                     .into_report()
diff --git a/crates/router/src/compatibility/stripe/refunds.rs b/crates/router/src/compatibility/stripe/refunds.rs
index dc147443828c..ad4accf6ca74 100644
--- a/crates/router/src/compatibility/stripe/refunds.rs
+++ b/crates/router/src/compatibility/stripe/refunds.rs
@@ -149,8 +149,8 @@ pub async fn refund_update(
     path: web::Path<String>,
     form_payload: web::Form<types::StripeUpdateRefundRequest>,
 ) -> HttpResponse {
-    let refund_id = path.into_inner();
-    let payload = form_payload.into_inner();
+    let mut payload = form_payload.into_inner();
+    payload.refund_id = path.into_inner();
     let create_refund_update_req: refund_types::RefundUpdateRequest = payload.into();
     let flow = Flow::RefundsUpdate;
 
@@ -169,9 +169,7 @@ pub async fn refund_update(
         state.into_inner(),
         &req,
         create_refund_update_req,
-        |state, auth, req| {
-            refunds::refund_update_core(state, auth.merchant_account, &refund_id, req)
-        },
+        |state, auth, req| refunds::refund_update_core(state, auth.merchant_account, req),
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
     ))
diff --git a/crates/router/src/compatibility/stripe/refunds/types.rs b/crates/router/src/compatibility/stripe/refunds/types.rs
index e1486186491a..8d65a09187d3 100644
--- a/crates/router/src/compatibility/stripe/refunds/types.rs
+++ b/crates/router/src/compatibility/stripe/refunds/types.rs
@@ -17,6 +17,8 @@ pub struct StripeCreateRefundRequest {
 
 #[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
 pub struct StripeUpdateRefundRequest {
+    #[serde(skip)]
+    pub refund_id: String,
     pub metadata: Option<pii::SecretSerdeValue>,
 }
 
@@ -58,6 +60,7 @@ impl From<StripeCreateRefundRequest> for refunds::RefundRequest {
 impl From<StripeUpdateRefundRequest> for refunds::RefundUpdateRequest {
     fn from(req: StripeUpdateRefundRequest) -> Self {
         Self {
+            refund_id: req.refund_id,
             metadata: req.metadata,
             reason: None,
         }
diff --git a/crates/router/src/compatibility/stripe/setup_intents.rs b/crates/router/src/compatibility/stripe/setup_intents.rs
index 311498e1af58..515e41ec91fa 100644
--- a/crates/router/src/compatibility/stripe/setup_intents.rs
+++ b/crates/router/src/compatibility/stripe/setup_intents.rs
@@ -69,6 +69,7 @@ pub async fn setup_intents_create(
                 req,
                 api::AuthFlow::Merchant,
                 payments::CallConnectorAction::Trigger,
+                None,
                 api_types::HeaderPayload::default(),
             )
         },
@@ -128,6 +129,7 @@ pub async fn setup_intents_retrieve(
                 payload,
                 auth_flow,
                 payments::CallConnectorAction::Trigger,
+                None,
                 api_types::HeaderPayload::default(),
             )
         },
@@ -200,6 +202,7 @@ pub async fn setup_intents_update(
                 req,
                 auth_flow,
                 payments::CallConnectorAction::Trigger,
+                None,
                 api_types::HeaderPayload::default(),
             )
         },
@@ -273,6 +276,7 @@ pub async fn setup_intents_confirm(
                 req,
                 auth_flow,
                 payments::CallConnectorAction::Trigger,
+                None,
                 api_types::HeaderPayload::default(),
             )
         },
diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs
index 71bf58f651cf..dde378e55925 100644
--- a/crates/router/src/compatibility/stripe/setup_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/setup_intents/types.rs
@@ -184,7 +184,19 @@ impl TryFrom<StripeSetupIntentRequest> for payments::PaymentsRequest {
             });
 
         let routing = routable_connector
-            .map(api_types::RoutingAlgorithm::Single)
+            .map(|connector| {
+                api_models::routing::RoutingAlgorithm::Single(Box::new(
+                    api_models::routing::RoutableConnectorChoice {
+                        #[cfg(feature = "backwards_compatibility")]
+                        choice_kind: api_models::routing::RoutableChoiceKind::FullStruct,
+                        connector,
+                        #[cfg(feature = "connector_choice_mca_id")]
+                        merchant_connector_id: None,
+                        #[cfg(not(feature = "connector_choice_mca_id"))]
+                        sub_label: None,
+                    },
+                ))
+            })
             .map(|r| {
                 serde_json::to_value(r)
                     .into_report()
diff --git a/crates/router/src/compatibility/wrap.rs b/crates/router/src/compatibility/wrap.rs
index f1892698acee..1ab156d32ad4 100644
--- a/crates/router/src/compatibility/wrap.rs
+++ b/crates/router/src/compatibility/wrap.rs
@@ -7,6 +7,7 @@ use serde::Serialize;
 
 use crate::{
     core::{api_locking, errors},
+    events::api_logs::ApiEventMetric,
     routes::{app::AppStateInfo, metrics},
     services::{self, api, authentication as auth, logger},
 };
@@ -25,13 +26,12 @@ where
     F: Fn(A, U, T) -> Fut,
     Fut: Future<Output = CustomResult<api::ApplicationResponse<Q>, E2>>,
     E2: ErrorSwitch<E> + std::error::Error + Send + Sync + 'static,
-    Q: Serialize + std::fmt::Debug + 'a,
+    Q: Serialize + std::fmt::Debug + 'a + ApiEventMetric,
     S: TryFrom<Q> + Serialize,
     E: Serialize + error_stack::Context + actix_web::ResponseError + Clone,
-    U: auth::AuthInfo,
     error_stack::Report<E>: services::EmbedError,
     errors::ApiErrorResponse: ErrorSwitch<E>,
-    T: std::fmt::Debug,
+    T: std::fmt::Debug + Serialize + ApiEventMetric,
     A: AppStateInfo + Clone,
 {
     let request_method = request.method().as_str();
diff --git a/crates/router/src/configs/defaults.rs b/crates/router/src/configs/defaults.rs
index c2e60bacb63e..8d58037343e0 100644
--- a/crates/router/src/configs/defaults.rs
+++ b/crates/router/src/configs/defaults.rs
@@ -49,9 +49,8 @@ impl Default for super::settings::Locker {
         Self {
             host: "localhost".into(),
             mock_locker: true,
-
+            basilisk_host: "localhost".into(),
             locker_signing_key_id: "1".into(),
-            redis_temp_locker_encryption_key: "".into(),
         }
     }
 }
@@ -104,6 +103,13 @@ impl Default for super::settings::DrainerSettings {
     }
 }
 
+#[cfg(feature = "kv_store")]
+impl Default for super::settings::KvConfig {
+    fn default() -> Self {
+        Self { ttl: 900 }
+    }
+}
+
 use super::settings::{
     Mandates, SupportedConnectorsForMandate, SupportedPaymentMethodTypesForMandate,
     SupportedPaymentMethodsForMandate,
diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs
index ec1ea7d77e1f..c5b71c6f7341 100644
--- a/crates/router/src/configs/settings.rs
+++ b/crates/router/src/configs/settings.rs
@@ -16,6 +16,8 @@ pub use router_env::config::{Log, LogConsole, LogFile, LogTelemetry};
 use scheduler::SchedulerSettings;
 use serde::{de::Error, Deserialize, Deserializer};
 
+#[cfg(feature = "olap")]
+use crate::analytics::AnalyticsConfig;
 use crate::{
     core::errors::{ApplicationError, ApplicationResult},
     env::{self, logger, Env},
@@ -52,7 +54,6 @@ pub enum Subcommand {
 #[derive(Clone)]
 pub struct ActiveKmsSecrets {
     pub jwekey: masking::Secret<Jwekey>,
-    pub redis_temp_locker_encryption_key: masking::Secret<String>,
 }
 
 #[derive(Debug, Deserialize, Clone, Default)]
@@ -102,6 +103,15 @@ pub struct Settings {
     pub lock_settings: LockSettings,
     pub temp_locker_enable_config: TempLockerEnableConfig,
     pub payment_link: PaymentLink,
+    #[cfg(feature = "olap")]
+    pub analytics: AnalyticsConfig,
+    #[cfg(feature = "kv_store")]
+    pub kv_config: KvConfig,
+}
+
+#[derive(Debug, Deserialize, Clone)]
+pub struct KvConfig {
+    pub ttl: u32,
 }
 
 #[derive(Debug, Deserialize, Clone, Default)]
@@ -411,8 +421,8 @@ pub struct Secrets {
 pub struct Locker {
     pub host: String,
     pub mock_locker: bool,
+    pub basilisk_host: String,
     pub locker_signing_key_id: String,
-    pub redis_temp_locker_encryption_key: String,
 }
 
 #[derive(Debug, Deserialize, Clone)]
@@ -492,17 +502,17 @@ impl From<QueueStrategy> for bb8::QueueStrategy {
 }
 
 #[cfg(not(feature = "kms"))]
-impl Into<storage_impl::config::Database> for Database {
-    fn into(self) -> storage_impl::config::Database {
-        storage_impl::config::Database {
-            username: self.username,
-            password: self.password,
-            host: self.host,
-            port: self.port,
-            dbname: self.dbname,
-            pool_size: self.pool_size,
-            connection_timeout: self.connection_timeout,
-            queue_strategy: self.queue_strategy.into(),
+impl From<Database> for storage_impl::config::Database {
+    fn from(val: Database) -> Self {
+        Self {
+            username: val.username,
+            password: val.password,
+            host: val.host,
+            port: val.port,
+            dbname: val.dbname,
+            pool_size: val.pool_size,
+            connection_timeout: val.connection_timeout,
+            queue_strategy: val.queue_strategy.into(),
         }
     }
 }
@@ -525,6 +535,7 @@ pub struct Connectors {
     pub applepay: ConnectorParams,
     pub authorizedotnet: ConnectorParams,
     pub bambora: ConnectorParams,
+    pub bankofamerica: ConnectorParams,
     pub bitpay: ConnectorParams,
     pub bluesnap: ConnectorParamsWithSecondaryBaseUrl,
     pub boku: ConnectorParams,
diff --git a/crates/router/src/configs/validations.rs b/crates/router/src/configs/validations.rs
index f9c1c4a9b38d..569262d0d210 100644
--- a/crates/router/src/configs/validations.rs
+++ b/crates/router/src/configs/validations.rs
@@ -56,19 +56,10 @@ impl super::settings::Locker {
         })?;
 
         when(
-            self.redis_temp_locker_encryption_key.is_default_or_empty(),
+            !self.mock_locker && self.basilisk_host.is_default_or_empty(),
             || {
                 Err(ApplicationError::InvalidConfigurationValueError(
-                    "redis_temp_locker_encryption_key must not be empty".into(),
-                ))
-            },
-        )?;
-
-        when(
-            self.redis_temp_locker_encryption_key.is_default_or_empty(),
-            || {
-                Err(ApplicationError::InvalidConfigurationValueError(
-                    "redis_temp_locker_encryption_key must not be empty".into(),
+                    "basilisk host must not be empty when mock locker is disabled".into(),
                 ))
             },
         )
diff --git a/crates/router/src/connector.rs b/crates/router/src/connector.rs
index 7849fd98a4d1..3a83fea0d910 100644
--- a/crates/router/src/connector.rs
+++ b/crates/router/src/connector.rs
@@ -3,6 +3,7 @@ pub mod adyen;
 pub mod airwallex;
 pub mod authorizedotnet;
 pub mod bambora;
+pub mod bankofamerica;
 pub mod bitpay;
 pub mod bluesnap;
 pub mod boku;
@@ -55,13 +56,14 @@ pub mod zen;
 pub use self::dummyconnector::DummyConnector;
 pub use self::{
     aci::Aci, adyen::Adyen, airwallex::Airwallex, authorizedotnet::Authorizedotnet,
-    bambora::Bambora, bitpay::Bitpay, bluesnap::Bluesnap, boku::Boku, braintree::Braintree,
-    cashtocode::Cashtocode, checkout::Checkout, coinbase::Coinbase, cryptopay::Cryptopay,
-    cybersource::Cybersource, dlocal::Dlocal, fiserv::Fiserv, forte::Forte, globalpay::Globalpay,
-    globepay::Globepay, gocardless::Gocardless, helcim::Helcim, iatapay::Iatapay, klarna::Klarna,
-    mollie::Mollie, multisafepay::Multisafepay, nexinets::Nexinets, nmi::Nmi, noon::Noon,
-    nuvei::Nuvei, opayo::Opayo, opennode::Opennode, payeezy::Payeezy, payme::Payme, paypal::Paypal,
-    payu::Payu, powertranz::Powertranz, prophetpay::Prophetpay, rapyd::Rapyd, shift4::Shift4,
-    square::Square, stax::Stax, stripe::Stripe, trustpay::Trustpay, tsys::Tsys, volt::Volt,
-    wise::Wise, worldline::Worldline, worldpay::Worldpay, zen::Zen,
+    bambora::Bambora, bankofamerica::Bankofamerica, bitpay::Bitpay, bluesnap::Bluesnap, boku::Boku,
+    braintree::Braintree, cashtocode::Cashtocode, checkout::Checkout, coinbase::Coinbase,
+    cryptopay::Cryptopay, cybersource::Cybersource, dlocal::Dlocal, fiserv::Fiserv, forte::Forte,
+    globalpay::Globalpay, globepay::Globepay, gocardless::Gocardless, helcim::Helcim,
+    iatapay::Iatapay, klarna::Klarna, mollie::Mollie, multisafepay::Multisafepay,
+    nexinets::Nexinets, nmi::Nmi, noon::Noon, nuvei::Nuvei, opayo::Opayo, opennode::Opennode,
+    payeezy::Payeezy, payme::Payme, paypal::Paypal, payu::Payu, powertranz::Powertranz,
+    prophetpay::Prophetpay, rapyd::Rapyd, shift4::Shift4, square::Square, stax::Stax,
+    stripe::Stripe, trustpay::Trustpay, tsys::Tsys, volt::Volt, wise::Wise, worldline::Worldline,
+    worldpay::Worldpay, zen::Zen,
 };
diff --git a/crates/router/src/connector/aci.rs b/crates/router/src/connector/aci.rs
index 0a6e0d8a6099..f6389c802f9e 100644
--- a/crates/router/src/connector/aci.rs
+++ b/crates/router/src/connector/aci.rs
@@ -30,7 +30,9 @@ impl ConnectorCommon for Aci {
     fn id(&self) -> &'static str {
         "aci"
     }
-
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Base
+    }
     fn common_get_content_type(&self) -> &'static str {
         "application/x-www-form-urlencoded"
     }
@@ -76,6 +78,7 @@ impl ConnectorCommon for Aci {
                     .collect::<Vec<String>>()
                     .join("; ")
             }),
+            attempt_status: None,
         })
     }
 }
@@ -198,7 +201,9 @@ impl
                 .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsSyncType::get_request_body(self, req)?)
+                .body(types::PaymentsSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -277,9 +282,16 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         // encode only for for urlencoded things.
-        let connector_req = aci::AciPaymentsRequest::try_from(req)?;
+        let connector_router_data = aci::AciRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+        let connector_req = aci::AciPaymentsRequest::try_from(&connector_router_data)?;
         let aci_req = types::RequestBody::log_and_get_request_body(
             &connector_req,
             utils::Encode::<aci::AciPaymentsRequest>::url_encode,
@@ -308,7 +320,9 @@ impl
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -377,6 +391,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = aci::AciCancelRequest::try_from(req)?;
         let aci_req = types::RequestBody::log_and_get_request_body(
@@ -397,7 +412,9 @@ impl
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -470,8 +487,15 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let connector_req = aci::AciRefundRequest::try_from(req)?;
+        let connector_router_data = aci::AciRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.refund_amount,
+            req,
+        ))?;
+        let connector_req = aci::AciRefundRequest::try_from(&connector_router_data)?;
         let body = types::RequestBody::log_and_get_request_body(
             &connector_req,
             utils::Encode::<aci::AciRefundRequest>::url_encode,
@@ -493,7 +517,9 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
                 .headers(types::RefundExecuteType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::RefundExecuteType::get_request_body(self, req)?)
+                .body(types::RefundExecuteType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/aci/transformers.rs b/crates/router/src/connector/aci/transformers.rs
index f6c1daffe4d8..f56369ed31ab 100644
--- a/crates/router/src/connector/aci/transformers.rs
+++ b/crates/router/src/connector/aci/transformers.rs
@@ -17,6 +17,38 @@ use crate::{
 
 type Error = error_stack::Report<errors::ConnectorError>;
 
+#[derive(Debug, Serialize)]
+pub struct AciRouterData<T> {
+    amount: String,
+    router_data: T,
+}
+
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for AciRouterData<T>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+
+    fn try_from(
+        (currency_unit, currency, amount, item): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        let amount = utils::get_amount_as_string(currency_unit, amount, currency)?;
+        Ok(Self {
+            amount,
+            router_data: item,
+        })
+    }
+}
+
 pub struct AciAuthType {
     pub api_key: Secret<String>,
     pub entity_id: Secret<String>,
@@ -101,14 +133,14 @@ impl TryFrom<&api_models::payments::WalletData> for PaymentDetails {
 
 impl
     TryFrom<(
-        &types::PaymentsAuthorizeRouterData,
+        &AciRouterData<&types::PaymentsAuthorizeRouterData>,
         &api_models::payments::BankRedirectData,
     )> for PaymentDetails
 {
     type Error = Error;
     fn try_from(
         value: (
-            &types::PaymentsAuthorizeRouterData,
+            &AciRouterData<&types::PaymentsAuthorizeRouterData>,
             &api_models::payments::BankRedirectData,
         ),
     ) -> Result<Self, Self::Error> {
@@ -202,9 +234,9 @@ impl
                     bank_account_bic: None,
                     bank_account_iban: None,
                     billing_country: Some(country.to_owned()),
-                    merchant_customer_id: Some(Secret::new(item.get_customer_id()?)),
+                    merchant_customer_id: Some(Secret::new(item.router_data.get_customer_id()?)),
                     merchant_transaction_id: Some(Secret::new(
-                        item.connector_request_reference_id.clone(),
+                        item.router_data.connector_request_reference_id.clone(),
                     )),
                     customer_email: None,
                 }))
@@ -348,10 +380,12 @@ pub enum AciPaymentType {
     Refund,
 }
 
-impl TryFrom<&types::PaymentsAuthorizeRouterData> for AciPaymentsRequest {
+impl TryFrom<&AciRouterData<&types::PaymentsAuthorizeRouterData>> for AciPaymentsRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
-        match item.request.payment_method_data.clone() {
+    fn try_from(
+        item: &AciRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
+        match item.router_data.request.payment_method_data.clone() {
             api::PaymentMethodData::Card(ref card_data) => Self::try_from((item, card_data)),
             api::PaymentMethodData::Wallet(ref wallet_data) => Self::try_from((item, wallet_data)),
             api::PaymentMethodData::PayLater(ref pay_later_data) => {
@@ -361,7 +395,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for AciPaymentsRequest {
                 Self::try_from((item, bank_redirect_data))
             }
             api::PaymentMethodData::MandatePayment => {
-                let mandate_id = item.request.mandate_id.clone().ok_or(
+                let mandate_id = item.router_data.request.mandate_id.clone().ok_or(
                     errors::ConnectorError::MissingRequiredField {
                         field_name: "mandate_id",
                     },
@@ -376,7 +410,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for AciPaymentsRequest {
             | api::PaymentMethodData::CardRedirect(_)
             | api::PaymentMethodData::Upi(_)
             | api::PaymentMethodData::Voucher(_) => Err(errors::ConnectorError::NotSupported {
-                message: format!("{:?}", item.payment_method),
+                message: format!("{:?}", item.router_data.payment_method),
                 connector: "Aci",
             })?,
         }
@@ -385,14 +419,14 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for AciPaymentsRequest {
 
 impl
     TryFrom<(
-        &types::PaymentsAuthorizeRouterData,
+        &AciRouterData<&types::PaymentsAuthorizeRouterData>,
         &api_models::payments::WalletData,
     )> for AciPaymentsRequest
 {
     type Error = Error;
     fn try_from(
         value: (
-            &types::PaymentsAuthorizeRouterData,
+            &AciRouterData<&types::PaymentsAuthorizeRouterData>,
             &api_models::payments::WalletData,
         ),
     ) -> Result<Self, Self::Error> {
@@ -404,21 +438,21 @@ impl
             txn_details,
             payment_method,
             instruction: None,
-            shopper_result_url: item.request.router_return_url.clone(),
+            shopper_result_url: item.router_data.request.router_return_url.clone(),
         })
     }
 }
 
 impl
     TryFrom<(
-        &types::PaymentsAuthorizeRouterData,
+        &AciRouterData<&types::PaymentsAuthorizeRouterData>,
         &api_models::payments::BankRedirectData,
     )> for AciPaymentsRequest
 {
     type Error = Error;
     fn try_from(
         value: (
-            &types::PaymentsAuthorizeRouterData,
+            &AciRouterData<&types::PaymentsAuthorizeRouterData>,
             &api_models::payments::BankRedirectData,
         ),
     ) -> Result<Self, Self::Error> {
@@ -430,21 +464,21 @@ impl
             txn_details,
             payment_method,
             instruction: None,
-            shopper_result_url: item.request.router_return_url.clone(),
+            shopper_result_url: item.router_data.request.router_return_url.clone(),
         })
     }
 }
 
 impl
     TryFrom<(
-        &types::PaymentsAuthorizeRouterData,
+        &AciRouterData<&types::PaymentsAuthorizeRouterData>,
         &api_models::payments::PayLaterData,
     )> for AciPaymentsRequest
 {
     type Error = Error;
     fn try_from(
         value: (
-            &types::PaymentsAuthorizeRouterData,
+            &AciRouterData<&types::PaymentsAuthorizeRouterData>,
             &api_models::payments::PayLaterData,
         ),
     ) -> Result<Self, Self::Error> {
@@ -456,15 +490,23 @@ impl
             txn_details,
             payment_method,
             instruction: None,
-            shopper_result_url: item.request.router_return_url.clone(),
+            shopper_result_url: item.router_data.request.router_return_url.clone(),
         })
     }
 }
 
-impl TryFrom<(&types::PaymentsAuthorizeRouterData, &api::Card)> for AciPaymentsRequest {
+impl
+    TryFrom<(
+        &AciRouterData<&types::PaymentsAuthorizeRouterData>,
+        &api::Card,
+    )> for AciPaymentsRequest
+{
     type Error = Error;
     fn try_from(
-        value: (&types::PaymentsAuthorizeRouterData, &api::Card),
+        value: (
+            &AciRouterData<&types::PaymentsAuthorizeRouterData>,
+            &api::Card,
+        ),
     ) -> Result<Self, Self::Error> {
         let (item, card_data) = value;
         let txn_details = get_transaction_details(item)?;
@@ -482,14 +524,14 @@ impl TryFrom<(&types::PaymentsAuthorizeRouterData, &api::Card)> for AciPaymentsR
 
 impl
     TryFrom<(
-        &types::PaymentsAuthorizeRouterData,
+        &AciRouterData<&types::PaymentsAuthorizeRouterData>,
         api_models::payments::MandateIds,
     )> for AciPaymentsRequest
 {
     type Error = Error;
     fn try_from(
         value: (
-            &types::PaymentsAuthorizeRouterData,
+            &AciRouterData<&types::PaymentsAuthorizeRouterData>,
             api_models::payments::MandateIds,
         ),
     ) -> Result<Self, Self::Error> {
@@ -501,32 +543,34 @@ impl
             txn_details,
             payment_method: PaymentDetails::Mandate,
             instruction,
-            shopper_result_url: item.request.router_return_url.clone(),
+            shopper_result_url: item.router_data.request.router_return_url.clone(),
         })
     }
 }
 
 fn get_transaction_details(
-    item: &types::PaymentsAuthorizeRouterData,
+    item: &AciRouterData<&types::PaymentsAuthorizeRouterData>,
 ) -> Result<TransactionDetails, error_stack::Report<errors::ConnectorError>> {
-    let auth = AciAuthType::try_from(&item.connector_auth_type)?;
+    let auth = AciAuthType::try_from(&item.router_data.connector_auth_type)?;
     Ok(TransactionDetails {
         entity_id: auth.entity_id,
-        amount: utils::to_currency_base_unit(item.request.amount, item.request.currency)?,
-        currency: item.request.currency.to_string(),
+        amount: item.amount.to_owned(),
+        currency: item.router_data.request.currency.to_string(),
         payment_type: AciPaymentType::Debit,
     })
 }
 
-fn get_instruction_details(item: &types::PaymentsAuthorizeRouterData) -> Option<Instruction> {
-    if item.request.setup_mandate_details.is_some() {
+fn get_instruction_details(
+    item: &AciRouterData<&types::PaymentsAuthorizeRouterData>,
+) -> Option<Instruction> {
+    if item.router_data.request.setup_mandate_details.is_some() {
         return Some(Instruction {
             mode: InstructionMode::Initial,
             transaction_type: InstructionType::Unscheduled,
             source: InstructionSource::CardholderInitiatedTransaction,
             create_registration: Some(true),
         });
-    } else if item.request.mandate_id.is_some() {
+    } else if item.router_data.request.mandate_id.is_some() {
         return Some(Instruction {
             mode: InstructionMode::Repeated,
             transaction_type: InstructionType::Unscheduled,
@@ -703,14 +747,13 @@ pub struct AciRefundRequest {
     pub entity_id: Secret<String>,
 }
 
-impl<F> TryFrom<&types::RefundsRouterData<F>> for AciRefundRequest {
+impl<F> TryFrom<&AciRouterData<&types::RefundsRouterData<F>>> for AciRefundRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
-        let amount =
-            utils::to_currency_base_unit(item.request.refund_amount, item.request.currency)?;
-        let currency = item.request.currency;
+    fn try_from(item: &AciRouterData<&types::RefundsRouterData<F>>) -> Result<Self, Self::Error> {
+        let amount = item.amount.to_owned();
+        let currency = item.router_data.request.currency;
         let payment_type = AciPaymentType::Refund;
-        let auth = AciAuthType::try_from(&item.connector_auth_type)?;
+        let auth = AciAuthType::try_from(&item.router_data.connector_auth_type)?;
 
         Ok(Self {
             amount,
diff --git a/crates/router/src/connector/adyen.rs b/crates/router/src/connector/adyen.rs
index 18a575b509cb..ef10fbb692fd 100644
--- a/crates/router/src/connector/adyen.rs
+++ b/crates/router/src/connector/adyen.rs
@@ -73,6 +73,7 @@ impl ConnectorCommon for Adyen {
             code: response.error_code,
             message: response.message,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -171,6 +172,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::SetupMandateRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let authorize_req = types::PaymentsAuthorizeRouterData::from((
             req,
@@ -202,7 +204,9 @@ impl
                 .url(&types::SetupMandateType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::SetupMandateType::get_headers(self, req, connectors)?)
-                .body(types::SetupMandateType::get_request_body(self, req)?)
+                .body(types::SetupMandateType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -251,6 +255,7 @@ impl
             code: response.error_code,
             message: response.message,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -304,6 +309,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = adyen::AdyenRouterData::try_from((
             &self.get_currency_unit(),
@@ -332,7 +338,9 @@ impl
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -366,6 +374,7 @@ impl
             code: response.error_code,
             message: response.message,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -395,6 +404,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::RouterData<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         // Adyen doesn't support PSync flow. We use PSync flow to fetch payment details,
         // specifically the redirect URL that takes the user to their Payment page. In non-redirection flows,
@@ -479,7 +489,7 @@ impl
         req: &types::RouterData<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>,
         connectors: &settings::Connectors,
     ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
-        let request_body = self.get_request_body(req)?;
+        let request_body = self.get_request_body(req, connectors)?;
         match request_body {
             Some(_) => Ok(Some(
                 services::RequestBuilder::new()
@@ -487,7 +497,9 @@ impl
                     .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                     .attach_default_headers()
                     .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-                    .body(types::PaymentsSyncType::get_request_body(self, req)?)
+                    .body(types::PaymentsSyncType::get_request_body(
+                        self, req, connectors,
+                    )?)
                     .build(),
             )),
             None => Ok(None),
@@ -533,6 +545,7 @@ impl
             code: response.error_code,
             message: response.message,
             reason: None,
+            attempt_status: None,
         })
     }
 
@@ -628,6 +641,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = adyen::AdyenRouterData::try_from((
             &self.get_currency_unit(),
@@ -660,7 +674,9 @@ impl
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -699,6 +715,7 @@ impl
             code: response.error_code,
             message: response.message,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -747,6 +764,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsBalanceRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = adyen::AdyenBalanceRequest::try_from(req)?;
 
@@ -771,7 +789,9 @@ impl
                 .headers(types::PaymentsBalanceType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsBalanceType::get_request_body(self, req)?)
+                .body(types::PaymentsBalanceType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -840,6 +860,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = adyen::AdyenCancelRequest::try_from(req)?;
 
@@ -861,7 +882,9 @@ impl
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -896,6 +919,7 @@ impl
             code: response.error_code,
             message: response.message,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -949,6 +973,7 @@ impl services::ConnectorIntegration<api::PoCancel, types::PayoutsData, types::Pa
     fn get_request_body(
         &self,
         req: &types::PayoutsRouterData<api::PoCancel>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = adyen::AdyenPayoutCancelRequest::try_from(req)?;
         let adyen_req = types::RequestBody::log_and_get_request_body(
@@ -969,7 +994,9 @@ impl services::ConnectorIntegration<api::PoCancel, types::PayoutsData, types::Pa
             .url(&types::PayoutCancelType::get_url(self, req, connectors)?)
             .attach_default_headers()
             .headers(types::PayoutCancelType::get_headers(self, req, connectors)?)
-            .body(types::PayoutCancelType::get_request_body(self, req)?)
+            .body(types::PayoutCancelType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
 
         Ok(Some(request))
@@ -1034,6 +1061,7 @@ impl services::ConnectorIntegration<api::PoCreate, types::PayoutsData, types::Pa
     fn get_request_body(
         &self,
         req: &types::PayoutsRouterData<api::PoCreate>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = adyen::AdyenRouterData::try_from((
             &self.get_currency_unit(),
@@ -1060,7 +1088,9 @@ impl services::ConnectorIntegration<api::PoCreate, types::PayoutsData, types::Pa
             .url(&types::PayoutCreateType::get_url(self, req, connectors)?)
             .attach_default_headers()
             .headers(types::PayoutCreateType::get_headers(self, req, connectors)?)
-            .body(types::PayoutCreateType::get_request_body(self, req)?)
+            .body(types::PayoutCreateType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
 
         Ok(Some(request))
@@ -1126,6 +1156,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PayoutsRouterData<api::PoEligibility>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = adyen::AdyenRouterData::try_from((
             &self.get_currency_unit(),
@@ -1156,7 +1187,9 @@ impl
             .headers(types::PayoutEligibilityType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::PayoutEligibilityType::get_request_body(self, req)?)
+            .body(types::PayoutEligibilityType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
 
         Ok(Some(request))
@@ -1235,6 +1268,7 @@ impl services::ConnectorIntegration<api::PoFulfill, types::PayoutsData, types::P
     fn get_request_body(
         &self,
         req: &types::PayoutsRouterData<api::PoFulfill>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = adyen::AdyenRouterData::try_from((
             &self.get_currency_unit(),
@@ -1263,7 +1297,9 @@ impl services::ConnectorIntegration<api::PoFulfill, types::PayoutsData, types::P
             .headers(types::PayoutFulfillType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::PayoutFulfillType::get_request_body(self, req)?)
+            .body(types::PayoutFulfillType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
 
         Ok(Some(request))
@@ -1333,6 +1369,7 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = adyen::AdyenRouterData::try_from((
             &self.get_currency_unit(),
@@ -1363,7 +1400,9 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
                 .headers(types::RefundExecuteType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::RefundExecuteType::get_request_body(self, req)?)
+                .body(types::RefundExecuteType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -1399,6 +1438,7 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
             code: response.error_code,
             message: response.message,
             reason: None,
+            attempt_status: None,
         })
     }
 }
diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs
index b0034a5eeb0b..ec21c9baa5e9 100644
--- a/crates/router/src/connector/adyen/transformers.rs
+++ b/crates/router/src/connector/adyen/transformers.rs
@@ -2906,6 +2906,7 @@ pub fn get_adyen_response(
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
             reason: response.refusal_reason,
             status_code,
+            attempt_status: None,
         })
     } else {
         None
@@ -2997,6 +2998,7 @@ pub fn get_redirection_response(
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
             reason: None,
             status_code,
+            attempt_status: None,
         })
     } else {
         None
@@ -3058,6 +3060,7 @@ pub fn get_present_to_shopper_response(
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
             reason: None,
             status_code,
+            attempt_status: None,
         })
     } else {
         None
@@ -3107,6 +3110,7 @@ pub fn get_qr_code_response(
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
             reason: None,
             status_code,
+            attempt_status: None,
         })
     } else {
         None
@@ -3144,6 +3148,7 @@ pub fn get_redirection_error_response(
         message: response.refusal_reason.clone(),
         reason: Some(response.refusal_reason),
         status_code,
+        attempt_status: None,
     });
     // We don't get connector transaction id for redirections in Adyen.
     let payments_response_data = types::PaymentsResponseData::TransactionResponse {
diff --git a/crates/router/src/connector/airwallex.rs b/crates/router/src/connector/airwallex.rs
index 8ef7ba08211e..5de7fc065e80 100644
--- a/crates/router/src/connector/airwallex.rs
+++ b/crates/router/src/connector/airwallex.rs
@@ -93,6 +93,7 @@ impl ConnectorCommon for Airwallex {
             code: response.code,
             message: response.message,
             reason: response.source,
+            attempt_status: None,
         })
     }
 }
@@ -183,7 +184,9 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
                 .attach_default_headers()
                 .headers(types::RefreshTokenType::get_headers(self, req, connectors)?)
                 .url(&types::RefreshTokenType::get_url(self, req, connectors)?)
-                .body(types::RefreshTokenType::get_request_body(self, req)?)
+                .body(types::RefreshTokenType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         );
         logger::debug!(payu_access_token_request=?req);
@@ -252,6 +255,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsInitRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = airwallex::AirwallexIntentRequest::try_from(req)?;
         let req = types::RequestBody::log_and_get_request_body(
@@ -273,7 +277,9 @@ impl
                 .url(&types::PaymentsInitType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsInitType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsInitType::get_request_body(self, req)?)
+                .body(types::PaymentsInitType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -372,6 +378,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = airwallex::AirwallexRouterData::try_from((
             &self.get_currency_unit(),
@@ -403,7 +410,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -546,6 +555,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCompleteAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = airwallex::AirwallexCompleteRequest::try_from(req)?;
 
@@ -571,7 +581,7 @@ impl
                     self, req, connectors,
                 )?)
                 .body(types::PaymentsCompleteAuthorizeType::get_request_body(
-                    self, req,
+                    self, req, connectors,
                 )?)
                 .build(),
         ))
@@ -634,6 +644,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = airwallex::AirwallexPaymentsCaptureRequest::try_from(req)?;
 
@@ -659,7 +670,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -732,6 +745,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = airwallex::AirwallexPaymentsCancelRequest::try_from(req)?;
 
@@ -772,7 +786,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -819,6 +835,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = airwallex::AirwallexRouterData::try_from((
             &self.get_currency_unit(),
@@ -847,7 +864,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -918,7 +937,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/airwallex/transformers.rs b/crates/router/src/connector/airwallex/transformers.rs
index 51258643c64c..031a8276bb0d 100644
--- a/crates/router/src/connector/airwallex/transformers.rs
+++ b/crates/router/src/connector/airwallex/transformers.rs
@@ -186,8 +186,18 @@ impl TryFrom<&AirwallexRouterData<&types::PaymentsAuthorizeRouterData>>
                 }))
             }
             api::PaymentMethodData::Wallet(ref wallet_data) => get_wallet_details(wallet_data),
-            _ => Err(errors::ConnectorError::NotImplemented(
-                "Unknown payment method".to_string(),
+            api::PaymentMethodData::PayLater(_)
+            | api::PaymentMethodData::BankRedirect(_)
+            | api::PaymentMethodData::BankDebit(_)
+            | api::PaymentMethodData::BankTransfer(_)
+            | api::PaymentMethodData::CardRedirect(_)
+            | api::PaymentMethodData::Crypto(_)
+            | api::PaymentMethodData::MandatePayment
+            | api::PaymentMethodData::Reward
+            | api::PaymentMethodData::Upi(_)
+            | api::PaymentMethodData::Voucher(_)
+            | api::PaymentMethodData::GiftCard(_) => Err(errors::ConnectorError::NotImplemented(
+                utils::get_unimplemented_payment_method_error_message("airwallex"),
             )),
         }?;
 
@@ -215,9 +225,35 @@ fn get_wallet_details(
                 payment_method_type: AirwallexPaymentType::Googlepay,
             }))
         }
-        _ => Err(errors::ConnectorError::NotImplemented(
-            "Payment method".to_string(),
-        ))?,
+        api_models::payments::WalletData::AliPayQr(_)
+        | api_models::payments::WalletData::AliPayRedirect(_)
+        | api_models::payments::WalletData::AliPayHkRedirect(_)
+        | api_models::payments::WalletData::MomoRedirect(_)
+        | api_models::payments::WalletData::KakaoPayRedirect(_)
+        | api_models::payments::WalletData::GoPayRedirect(_)
+        | api_models::payments::WalletData::GcashRedirect(_)
+        | api_models::payments::WalletData::ApplePay(_)
+        | api_models::payments::WalletData::ApplePayRedirect(_)
+        | api_models::payments::WalletData::ApplePayThirdPartySdk(_)
+        | api_models::payments::WalletData::DanaRedirect {}
+        | api_models::payments::WalletData::GooglePayRedirect(_)
+        | api_models::payments::WalletData::GooglePayThirdPartySdk(_)
+        | api_models::payments::WalletData::MbWayRedirect(_)
+        | api_models::payments::WalletData::MobilePayRedirect(_)
+        | api_models::payments::WalletData::PaypalRedirect(_)
+        | api_models::payments::WalletData::PaypalSdk(_)
+        | api_models::payments::WalletData::SamsungPay(_)
+        | api_models::payments::WalletData::TwintRedirect {}
+        | api_models::payments::WalletData::VippsRedirect {}
+        | api_models::payments::WalletData::TouchNGoRedirect(_)
+        | api_models::payments::WalletData::WeChatPayRedirect(_)
+        | api_models::payments::WalletData::WeChatPayQr(_)
+        | api_models::payments::WalletData::CashappQr(_)
+        | api_models::payments::WalletData::SwishQr(_) => {
+            Err(errors::ConnectorError::NotImplemented(
+                utils::get_unimplemented_payment_method_error_message("airwallex"),
+            ))?
+        }
     };
     Ok(wallet_details)
 }
diff --git a/crates/router/src/connector/authorizedotnet.rs b/crates/router/src/connector/authorizedotnet.rs
index d25e62391b58..7c3c234daecf 100644
--- a/crates/router/src/connector/authorizedotnet.rs
+++ b/crates/router/src/connector/authorizedotnet.rs
@@ -145,6 +145,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = authorizedotnet::AuthorizedotnetRouterData::try_from((
             &self.get_currency_unit(),
@@ -176,7 +177,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -240,6 +243,7 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
     fn get_request_body(
         &self,
         req: &types::PaymentsSyncRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = authorizedotnet::AuthorizedotnetCreateSyncRequest::try_from(req)?;
         let sync_request = types::RequestBody::log_and_get_request_body(
@@ -261,7 +265,9 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
             .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
             .attach_default_headers()
             .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-            .body(types::PaymentsSyncType::get_request_body(self, req)?)
+            .body(types::PaymentsSyncType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -325,6 +331,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = authorizedotnet::AuthorizedotnetRouterData::try_from((
             &self.get_currency_unit(),
@@ -362,7 +369,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -424,6 +433,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = authorizedotnet::CancelOrCaptureTransactionRequest::try_from(req)?;
 
@@ -445,7 +455,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -513,6 +525,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = authorizedotnet::AuthorizedotnetRouterData::try_from((
             &self.get_currency_unit(),
@@ -542,7 +555,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -606,6 +621,7 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::RSync>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = authorizedotnet::AuthorizedotnetRouterData::try_from((
             &self.get_currency_unit(),
@@ -634,7 +650,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
             .url(&types::RefundSyncType::get_url(self, req, connectors)?)
             .attach_default_headers()
             .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-            .body(types::RefundSyncType::get_request_body(self, req)?)
+            .body(types::RefundSyncType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -701,6 +719,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCompleteAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = authorizedotnet::AuthorizedotnetRouterData::try_from((
             &self.get_currency_unit(),
@@ -735,7 +754,7 @@ impl
                     self, req, connectors,
                 )?)
                 .body(types::PaymentsCompleteAuthorizeType::get_request_body(
-                    self, req,
+                    self, req, connectors,
                 )?)
                 .build(),
         ))
@@ -893,6 +912,7 @@ fn get_error_response(
                     message: error.error_text.to_owned(),
                     reason: Some(error.error_text),
                     status_code,
+                    attempt_status: None,
                 })
             })
             .unwrap_or_else(|| types::ErrorResponse {
@@ -900,6 +920,7 @@ fn get_error_response(
                 message: consts::NO_ERROR_MESSAGE.to_string(),
                 reason: None,
                 status_code,
+                attempt_status: None,
             })),
         Some(authorizedotnet::TransactionResponse::AuthorizedotnetTransactionResponseError(_))
         | None => {
@@ -909,6 +930,7 @@ fn get_error_response(
                 message: message.to_string(),
                 reason: Some(message.to_string()),
                 status_code,
+                attempt_status: None,
             })
         }
     }
diff --git a/crates/router/src/connector/authorizedotnet/transformers.rs b/crates/router/src/connector/authorizedotnet/transformers.rs
index 20d78729a1be..884504154e8f 100644
--- a/crates/router/src/connector/authorizedotnet/transformers.rs
+++ b/crates/router/src/connector/authorizedotnet/transformers.rs
@@ -261,6 +261,7 @@ struct TransactionVoidOrCaptureRequest {
 pub struct AuthorizedotnetPaymentsRequest {
     merchant_authentication: AuthorizedotnetAuthType,
     transaction_request: TransactionRequest,
+    ref_id: String,
 }
 
 #[derive(Debug, Serialize)]
@@ -332,6 +333,7 @@ impl TryFrom<&AuthorizedotnetRouterData<&types::PaymentsAuthorizeRouterData>>
             create_transaction_request: AuthorizedotnetPaymentsRequest {
                 merchant_authentication,
                 transaction_request,
+                ref_id: item.router_data.connector_request_reference_id.clone(),
             },
         })
     }
@@ -571,6 +573,7 @@ impl<F, T>
                         message: error.error_text.clone(),
                         reason: None,
                         status_code: item.http_code,
+                        attempt_status: None,
                     })
                 });
                 let metadata = transaction_response
@@ -645,6 +648,7 @@ impl<F, T>
                         message: error.error_text.clone(),
                         reason: None,
                         status_code: item.http_code,
+                        attempt_status: None,
                     })
                 });
                 let metadata = transaction_response
@@ -787,6 +791,7 @@ impl<F> TryFrom<types::RefundsResponseRouterData<F, AuthorizedotnetRefundRespons
                 message: error.error_text.clone(),
                 reason: None,
                 status_code: item.http_code,
+                attempt_status: None,
             })
         });
 
@@ -1019,6 +1024,7 @@ fn get_err_response(status_code: u16, message: ResponseMessages) -> types::Error
         message: message.message[0].text.clone(),
         reason: None,
         status_code,
+        attempt_status: None,
     }
 }
 
diff --git a/crates/router/src/connector/bambora.rs b/crates/router/src/connector/bambora.rs
index d5e8119b66c8..802be26408df 100644
--- a/crates/router/src/connector/bambora.rs
+++ b/crates/router/src/connector/bambora.rs
@@ -95,6 +95,7 @@ impl ConnectorCommon for Bambora {
             code: response.code.to_string(),
             message: response.message,
             reason: Some(serde_json::to_string(&response.details).unwrap_or_default()),
+            attempt_status: None,
         })
     }
 }
@@ -172,6 +173,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let request = bambora::BamboraPaymentsRequest::try_from(req)?;
 
@@ -194,7 +196,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(self.get_request_body(req)?)
+                .body(self.get_request_body(req, connectors)?)
                 .build(),
         ))
     }
@@ -344,6 +346,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = bambora::BamboraPaymentsCaptureRequest::try_from(req)?;
         let bambora_req = types::RequestBody::log_and_get_request_body(
@@ -367,7 +370,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(self.get_request_body(req)?)
+                .body(self.get_request_body(req, connectors)?)
                 .build(),
         ))
     }
@@ -437,6 +440,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let request = bambora::BamboraPaymentsRequest::try_from(req)?;
 
@@ -463,7 +467,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -534,6 +540,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = bambora::BamboraRefundRequest::try_from(req)?;
         let bambora_req = types::RequestBody::log_and_get_request_body(
@@ -556,7 +563,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -625,7 +634,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -740,6 +751,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCompleteAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let request = bambora::BamboraThreedsContinueRequest::try_from(&req.request)?;
 
@@ -765,7 +777,7 @@ impl
                 self, req, connectors,
             )?)
             .body(types::PaymentsCompleteAuthorizeType::get_request_body(
-                self, req,
+                self, req, connectors,
             )?)
             .build();
         Ok(Some(request))
diff --git a/crates/router/src/connector/bambora/transformers.rs b/crates/router/src/connector/bambora/transformers.rs
index bfcd98462924..e686186c901b 100644
--- a/crates/router/src/connector/bambora/transformers.rs
+++ b/crates/router/src/connector/bambora/transformers.rs
@@ -214,7 +214,7 @@ impl<F, T>
                     mandate_reference: None,
                     connector_metadata: None,
                     network_txn_id: None,
-                    connector_response_reference_id: None,
+                    connector_response_reference_id: Some(pg_response.order_number.to_string()),
                 }),
                 ..item.data
             }),
@@ -238,7 +238,9 @@ impl<F, T>
                             .change_context(errors::ConnectorError::ResponseHandlingFailed)?,
                         ),
                         network_txn_id: None,
-                        connector_response_reference_id: None,
+                        connector_response_reference_id: Some(
+                            item.data.connector_request_reference_id.to_string(),
+                        ),
                     }),
                     ..item.data
                 })
diff --git a/crates/router/src/connector/bankofamerica.rs b/crates/router/src/connector/bankofamerica.rs
new file mode 100644
index 000000000000..84870f7407fb
--- /dev/null
+++ b/crates/router/src/connector/bankofamerica.rs
@@ -0,0 +1,548 @@
+pub mod transformers;
+
+use std::fmt::Debug;
+
+use error_stack::{IntoReport, ResultExt};
+use masking::ExposeInterface;
+use transformers as bankofamerica;
+
+use crate::{
+    configs::settings,
+    core::errors::{self, CustomResult},
+    headers,
+    services::{
+        self,
+        request::{self, Mask},
+        ConnectorIntegration, ConnectorValidation,
+    },
+    types::{
+        self,
+        api::{self, ConnectorCommon, ConnectorCommonExt},
+        ErrorResponse, Response,
+    },
+    utils::{self, BytesExt},
+};
+
+#[derive(Debug, Clone)]
+pub struct Bankofamerica;
+
+impl api::Payment for Bankofamerica {}
+impl api::PaymentSession for Bankofamerica {}
+impl api::ConnectorAccessToken for Bankofamerica {}
+impl api::MandateSetup for Bankofamerica {}
+impl api::PaymentAuthorize for Bankofamerica {}
+impl api::PaymentSync for Bankofamerica {}
+impl api::PaymentCapture for Bankofamerica {}
+impl api::PaymentVoid for Bankofamerica {}
+impl api::Refund for Bankofamerica {}
+impl api::RefundExecute for Bankofamerica {}
+impl api::RefundSync for Bankofamerica {}
+impl api::PaymentToken for Bankofamerica {}
+
+impl
+    ConnectorIntegration<
+        api::PaymentMethodToken,
+        types::PaymentMethodTokenizationData,
+        types::PaymentsResponseData,
+    > for Bankofamerica
+{
+    // Not Implemented (R)
+}
+
+impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Bankofamerica
+where
+    Self: ConnectorIntegration<Flow, Request, Response>,
+{
+    fn build_headers(
+        &self,
+        req: &types::RouterData<Flow, Request, Response>,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        let mut header = vec![(
+            headers::CONTENT_TYPE.to_string(),
+            self.get_content_type().to_string().into(),
+        )];
+        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
+        header.append(&mut api_key);
+        Ok(header)
+    }
+}
+
+impl ConnectorCommon for Bankofamerica {
+    fn id(&self) -> &'static str {
+        "bankofamerica"
+    }
+
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Minor
+    }
+
+    fn common_get_content_type(&self) -> &'static str {
+        "application/json"
+    }
+
+    fn base_url<'a>(&self, connectors: &'a settings::Connectors) -> &'a str {
+        connectors.bankofamerica.base_url.as_ref()
+    }
+
+    fn get_auth_header(
+        &self,
+        auth_type: &types::ConnectorAuthType,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        let auth = bankofamerica::BankofamericaAuthType::try_from(auth_type)
+            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
+        Ok(vec![(
+            headers::AUTHORIZATION.to_string(),
+            auth.api_key.expose().into_masked(),
+        )])
+    }
+
+    fn build_error_response(
+        &self,
+        res: Response,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        let response: bankofamerica::BankofamericaErrorResponse = res
+            .response
+            .parse_struct("BankofamericaErrorResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+
+        Ok(ErrorResponse {
+            status_code: res.status_code,
+            code: response.code,
+            message: response.message,
+            reason: response.reason,
+            attempt_status: None,
+        })
+    }
+}
+
+impl ConnectorValidation for Bankofamerica {
+    //TODO: implement functions when support enabled
+}
+
+impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::PaymentsResponseData>
+    for Bankofamerica
+{
+    //TODO: implement sessions flow
+}
+
+impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, types::AccessToken>
+    for Bankofamerica
+{
+}
+
+impl
+    ConnectorIntegration<
+        api::SetupMandate,
+        types::SetupMandateRequestData,
+        types::PaymentsResponseData,
+    > for Bankofamerica
+{
+}
+
+impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData>
+    for Bankofamerica
+{
+    fn get_headers(
+        &self,
+        req: &types::PaymentsAuthorizeRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_url(
+        &self,
+        _req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
+    }
+
+    fn get_request_body(
+        &self,
+        req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
+        let connector_router_data = bankofamerica::BankofamericaRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+        let req_obj =
+            bankofamerica::BankofamericaPaymentsRequest::try_from(&connector_router_data)?;
+        let bankofamerica_req = types::RequestBody::log_and_get_request_body(
+            &req_obj,
+            utils::Encode::<bankofamerica::BankofamericaPaymentsRequest>::encode_to_string_of_json,
+        )
+        .change_context(errors::ConnectorError::RequestEncodingFailed)?;
+        Ok(Some(bankofamerica_req))
+    }
+
+    fn build_request(
+        &self,
+        req: &types::PaymentsAuthorizeRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        Ok(Some(
+            services::RequestBuilder::new()
+                .method(services::Method::Post)
+                .url(&types::PaymentsAuthorizeType::get_url(
+                    self, req, connectors,
+                )?)
+                .attach_default_headers()
+                .headers(types::PaymentsAuthorizeType::get_headers(
+                    self, req, connectors,
+                )?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
+                .build(),
+        ))
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::PaymentsAuthorizeRouterData,
+        res: Response,
+    ) -> CustomResult<types::PaymentsAuthorizeRouterData, errors::ConnectorError> {
+        let response: bankofamerica::BankofamericaPaymentsResponse = res
+            .response
+            .parse_struct("Bankofamerica PaymentsAuthorizeResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+
+    fn get_error_response(
+        &self,
+        res: Response,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res)
+    }
+}
+
+impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
+    for Bankofamerica
+{
+    fn get_headers(
+        &self,
+        req: &types::PaymentsSyncRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_url(
+        &self,
+        _req: &types::PaymentsSyncRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
+    }
+
+    fn build_request(
+        &self,
+        req: &types::PaymentsSyncRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        Ok(Some(
+            services::RequestBuilder::new()
+                .method(services::Method::Get)
+                .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
+                .attach_default_headers()
+                .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
+                .build(),
+        ))
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::PaymentsSyncRouterData,
+        res: Response,
+    ) -> CustomResult<types::PaymentsSyncRouterData, errors::ConnectorError> {
+        let response: bankofamerica::BankofamericaPaymentsResponse = res
+            .response
+            .parse_struct("bankofamerica PaymentsSyncResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+
+    fn get_error_response(
+        &self,
+        res: Response,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res)
+    }
+}
+
+impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::PaymentsResponseData>
+    for Bankofamerica
+{
+    fn get_headers(
+        &self,
+        req: &types::PaymentsCaptureRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_url(
+        &self,
+        _req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
+    }
+
+    fn get_request_body(
+        &self,
+        _req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
+        Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into())
+    }
+
+    fn build_request(
+        &self,
+        req: &types::PaymentsCaptureRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        Ok(Some(
+            services::RequestBuilder::new()
+                .method(services::Method::Post)
+                .url(&types::PaymentsCaptureType::get_url(self, req, connectors)?)
+                .attach_default_headers()
+                .headers(types::PaymentsCaptureType::get_headers(
+                    self, req, connectors,
+                )?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
+                .build(),
+        ))
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::PaymentsCaptureRouterData,
+        res: Response,
+    ) -> CustomResult<types::PaymentsCaptureRouterData, errors::ConnectorError> {
+        let response: bankofamerica::BankofamericaPaymentsResponse = res
+            .response
+            .parse_struct("Bankofamerica PaymentsCaptureResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+
+    fn get_error_response(
+        &self,
+        res: Response,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res)
+    }
+}
+
+impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsResponseData>
+    for Bankofamerica
+{
+}
+
+impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsResponseData>
+    for Bankofamerica
+{
+    fn get_headers(
+        &self,
+        req: &types::RefundsRouterData<api::Execute>,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_url(
+        &self,
+        _req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
+    }
+
+    fn get_request_body(
+        &self,
+        req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
+        let connector_router_data = bankofamerica::BankofamericaRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.refund_amount,
+            req,
+        ))?;
+        let req_obj = bankofamerica::BankofamericaRefundRequest::try_from(&connector_router_data)?;
+        let bankofamerica_req = types::RequestBody::log_and_get_request_body(
+            &req_obj,
+            utils::Encode::<bankofamerica::BankofamericaRefundRequest>::encode_to_string_of_json,
+        )
+        .change_context(errors::ConnectorError::RequestEncodingFailed)?;
+        Ok(Some(bankofamerica_req))
+    }
+
+    fn build_request(
+        &self,
+        req: &types::RefundsRouterData<api::Execute>,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        let request = services::RequestBuilder::new()
+            .method(services::Method::Post)
+            .url(&types::RefundExecuteType::get_url(self, req, connectors)?)
+            .attach_default_headers()
+            .headers(types::RefundExecuteType::get_headers(
+                self, req, connectors,
+            )?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
+            .build();
+        Ok(Some(request))
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::RefundsRouterData<api::Execute>,
+        res: Response,
+    ) -> CustomResult<types::RefundsRouterData<api::Execute>, errors::ConnectorError> {
+        let response: bankofamerica::RefundResponse = res
+            .response
+            .parse_struct("bankofamerica RefundResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+
+    fn get_error_response(
+        &self,
+        res: Response,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res)
+    }
+}
+
+impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponseData>
+    for Bankofamerica
+{
+    fn get_headers(
+        &self,
+        req: &types::RefundSyncRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_url(
+        &self,
+        _req: &types::RefundSyncRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
+    }
+
+    fn build_request(
+        &self,
+        req: &types::RefundSyncRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        Ok(Some(
+            services::RequestBuilder::new()
+                .method(services::Method::Get)
+                .url(&types::RefundSyncType::get_url(self, req, connectors)?)
+                .attach_default_headers()
+                .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
+                .build(),
+        ))
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::RefundSyncRouterData,
+        res: Response,
+    ) -> CustomResult<types::RefundSyncRouterData, errors::ConnectorError> {
+        let response: bankofamerica::RefundResponse = res
+            .response
+            .parse_struct("bankofamerica RefundSyncResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+
+    fn get_error_response(
+        &self,
+        res: Response,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res)
+    }
+}
+
+#[async_trait::async_trait]
+impl api::IncomingWebhook for Bankofamerica {
+    fn get_webhook_object_reference_id(
+        &self,
+        _request: &api::IncomingWebhookRequestDetails<'_>,
+    ) -> CustomResult<api::webhooks::ObjectReferenceId, errors::ConnectorError> {
+        Err(errors::ConnectorError::WebhooksNotImplemented).into_report()
+    }
+
+    fn get_webhook_event_type(
+        &self,
+        _request: &api::IncomingWebhookRequestDetails<'_>,
+    ) -> CustomResult<api::IncomingWebhookEvent, errors::ConnectorError> {
+        Err(errors::ConnectorError::WebhooksNotImplemented).into_report()
+    }
+
+    fn get_webhook_resource_object(
+        &self,
+        _request: &api::IncomingWebhookRequestDetails<'_>,
+    ) -> CustomResult<serde_json::Value, errors::ConnectorError> {
+        Err(errors::ConnectorError::WebhooksNotImplemented).into_report()
+    }
+}
diff --git a/crates/router/src/connector/bankofamerica/transformers.rs b/crates/router/src/connector/bankofamerica/transformers.rs
new file mode 100644
index 000000000000..a396c47a4ced
--- /dev/null
+++ b/crates/router/src/connector/bankofamerica/transformers.rs
@@ -0,0 +1,250 @@
+use masking::Secret;
+use serde::{Deserialize, Serialize};
+
+use crate::{
+    connector::utils::PaymentsAuthorizeRequestData,
+    core::errors,
+    types::{self, api, storage::enums},
+};
+
+//TODO: Fill the struct with respective fields
+pub struct BankofamericaRouterData<T> {
+    pub amount: i64, // The type of amount that a connector accepts, for example, String, i64, f64, etc.
+    pub router_data: T,
+}
+
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for BankofamericaRouterData<T>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        (_currency_unit, _currency, amount, item): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        //Todo :  use utils to convert the amount to the type of amount that a connector accepts
+        Ok(Self {
+            amount,
+            router_data: item,
+        })
+    }
+}
+
+//TODO: Fill the struct with respective fields
+#[derive(Default, Debug, Serialize, Eq, PartialEq)]
+pub struct BankofamericaPaymentsRequest {
+    amount: i64,
+    card: BankofamericaCard,
+}
+
+#[derive(Default, Debug, Serialize, Eq, PartialEq)]
+pub struct BankofamericaCard {
+    name: Secret<String>,
+    number: cards::CardNumber,
+    expiry_month: Secret<String>,
+    expiry_year: Secret<String>,
+    cvc: Secret<String>,
+    complete: bool,
+}
+
+impl TryFrom<&BankofamericaRouterData<&types::PaymentsAuthorizeRouterData>>
+    for BankofamericaPaymentsRequest
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: &BankofamericaRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
+        match item.router_data.request.payment_method_data.clone() {
+            api::PaymentMethodData::Card(req_card) => {
+                let card = BankofamericaCard {
+                    name: req_card.card_holder_name,
+                    number: req_card.card_number,
+                    expiry_month: req_card.card_exp_month,
+                    expiry_year: req_card.card_exp_year,
+                    cvc: req_card.card_cvc,
+                    complete: item.router_data.request.is_auto_capture()?,
+                };
+                Ok(Self {
+                    amount: item.amount.to_owned(),
+                    card,
+                })
+            }
+            _ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()),
+        }
+    }
+}
+
+//TODO: Fill the struct with respective fields
+// Auth Struct
+pub struct BankofamericaAuthType {
+    pub(super) api_key: Secret<String>,
+}
+
+impl TryFrom<&types::ConnectorAuthType> for BankofamericaAuthType {
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(auth_type: &types::ConnectorAuthType) -> Result<Self, Self::Error> {
+        match auth_type {
+            types::ConnectorAuthType::HeaderKey { api_key } => Ok(Self {
+                api_key: api_key.to_owned(),
+            }),
+            _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
+        }
+    }
+}
+// PaymentsResponse
+//TODO: Append the remaining status flags
+#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
+#[serde(rename_all = "lowercase")]
+pub enum BankofamericaPaymentStatus {
+    Succeeded,
+    Failed,
+    #[default]
+    Processing,
+}
+
+impl From<BankofamericaPaymentStatus> for enums::AttemptStatus {
+    fn from(item: BankofamericaPaymentStatus) -> Self {
+        match item {
+            BankofamericaPaymentStatus::Succeeded => Self::Charged,
+            BankofamericaPaymentStatus::Failed => Self::Failure,
+            BankofamericaPaymentStatus::Processing => Self::Authorizing,
+        }
+    }
+}
+
+//TODO: Fill the struct with respective fields
+#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
+pub struct BankofamericaPaymentsResponse {
+    status: BankofamericaPaymentStatus,
+    id: String,
+}
+
+impl<F, T>
+    TryFrom<
+        types::ResponseRouterData<F, BankofamericaPaymentsResponse, T, types::PaymentsResponseData>,
+    > for types::RouterData<F, T, types::PaymentsResponseData>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: types::ResponseRouterData<
+            F,
+            BankofamericaPaymentsResponse,
+            T,
+            types::PaymentsResponseData,
+        >,
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            status: enums::AttemptStatus::from(item.response.status),
+            response: Ok(types::PaymentsResponseData::TransactionResponse {
+                resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
+                redirection_data: None,
+                mandate_reference: None,
+                connector_metadata: None,
+                network_txn_id: None,
+                connector_response_reference_id: None,
+            }),
+            ..item.data
+        })
+    }
+}
+
+//TODO: Fill the struct with respective fields
+// REFUND :
+// Type definition for RefundRequest
+#[derive(Default, Debug, Serialize)]
+pub struct BankofamericaRefundRequest {
+    pub amount: i64,
+}
+
+impl<F> TryFrom<&BankofamericaRouterData<&types::RefundsRouterData<F>>>
+    for BankofamericaRefundRequest
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: &BankofamericaRouterData<&types::RefundsRouterData<F>>,
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            amount: item.amount.to_owned(),
+        })
+    }
+}
+
+// Type definition for Refund Response
+
+#[allow(dead_code)]
+#[derive(Debug, Serialize, Default, Deserialize, Clone)]
+pub enum RefundStatus {
+    Succeeded,
+    Failed,
+    #[default]
+    Processing,
+}
+
+impl From<RefundStatus> for enums::RefundStatus {
+    fn from(item: RefundStatus) -> Self {
+        match item {
+            RefundStatus::Succeeded => Self::Success,
+            RefundStatus::Failed => Self::Failure,
+            RefundStatus::Processing => Self::Pending,
+            //TODO: Review mapping
+        }
+    }
+}
+
+//TODO: Fill the struct with respective fields
+#[derive(Default, Debug, Clone, Serialize, Deserialize)]
+pub struct RefundResponse {
+    id: String,
+    status: RefundStatus,
+}
+
+impl TryFrom<types::RefundsResponseRouterData<api::Execute, RefundResponse>>
+    for types::RefundsRouterData<api::Execute>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: types::RefundsResponseRouterData<api::Execute, RefundResponse>,
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            response: Ok(types::RefundsResponseData {
+                connector_refund_id: item.response.id.to_string(),
+                refund_status: enums::RefundStatus::from(item.response.status),
+            }),
+            ..item.data
+        })
+    }
+}
+
+impl TryFrom<types::RefundsResponseRouterData<api::RSync, RefundResponse>>
+    for types::RefundsRouterData<api::RSync>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: types::RefundsResponseRouterData<api::RSync, RefundResponse>,
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            response: Ok(types::RefundsResponseData {
+                connector_refund_id: item.response.id.to_string(),
+                refund_status: enums::RefundStatus::from(item.response.status),
+            }),
+            ..item.data
+        })
+    }
+}
+
+//TODO: Fill the struct with respective fields
+#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
+pub struct BankofamericaErrorResponse {
+    pub status_code: u16,
+    pub code: String,
+    pub message: String,
+    pub reason: Option<String>,
+}
diff --git a/crates/router/src/connector/bitpay.rs b/crates/router/src/connector/bitpay.rs
index 2dc634426f3e..dc4571b75746 100644
--- a/crates/router/src/connector/bitpay.rs
+++ b/crates/router/src/connector/bitpay.rs
@@ -82,6 +82,10 @@ impl ConnectorCommon for Bitpay {
         "bitpay"
     }
 
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Minor
+    }
+
     fn common_get_content_type(&self) -> &'static str {
         "application/json"
     }
@@ -116,6 +120,7 @@ impl ConnectorCommon for Bitpay {
                 .unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()),
             message: response.error,
             reason: response.message,
+            attempt_status: None,
         })
     }
 }
@@ -168,8 +173,15 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let req_obj = bitpay::BitpayPaymentsRequest::try_from(req)?;
+        let connector_router_data = bitpay::BitpayRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+        let req_obj = bitpay::BitpayPaymentsRequest::try_from(&connector_router_data)?;
 
         let bitpay_req = types::RequestBody::log_and_get_request_body(
             &req_obj,
@@ -194,7 +206,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/bitpay/transformers.rs b/crates/router/src/connector/bitpay/transformers.rs
index f99729da16d6..89dd2368b2b7 100644
--- a/crates/router/src/connector/bitpay/transformers.rs
+++ b/crates/router/src/connector/bitpay/transformers.rs
@@ -9,6 +9,37 @@ use crate::{
     types::{self, api, storage::enums, ConnectorAuthType},
 };
 
+#[derive(Debug, Serialize)]
+pub struct BitpayRouterData<T> {
+    pub amount: i64,
+    pub router_data: T,
+}
+
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for BitpayRouterData<T>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+
+    fn try_from(
+        (_currency_unit, _currency, amount, router_data): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            amount,
+            router_data,
+        })
+    }
+}
+
 #[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
 #[serde(rename_all = "lowercase")]
 pub enum TransactionSpeed {
@@ -29,11 +60,14 @@ pub struct BitpayPaymentsRequest {
     notification_url: String,
     transaction_speed: TransactionSpeed,
     token: Secret<String>,
+    order_id: String,
 }
 
-impl TryFrom<&types::PaymentsAuthorizeRouterData> for BitpayPaymentsRequest {
+impl TryFrom<&BitpayRouterData<&types::PaymentsAuthorizeRouterData>> for BitpayPaymentsRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
+    fn try_from(
+        item: &BitpayRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
         get_crypto_specific_payment_data(item)
     }
 }
@@ -100,6 +134,7 @@ pub struct BitpayPaymentResponseData {
     pub expiration_time: Option<i64>,
     pub current_time: Option<i64>,
     pub id: String,
+    pub order_id: Option<String>,
     pub low_fee_detected: Option<bool>,
     pub display_amount_paid: Option<String>,
     pub exception_status: ExceptionStatus,
@@ -128,7 +163,7 @@ impl<F, T>
             .data
             .url
             .map(|x| services::RedirectForm::from((x, services::Method::Get)));
-        let connector_id = types::ResponseId::ConnectorTransactionId(item.response.data.id);
+        let connector_id = types::ResponseId::ConnectorTransactionId(item.response.data.id.clone());
         let attempt_status = item.response.data.status;
         Ok(Self {
             status: enums::AttemptStatus::from(attempt_status),
@@ -138,7 +173,11 @@ impl<F, T>
                 mandate_reference: None,
                 connector_metadata: None,
                 network_txn_id: None,
-                connector_response_reference_id: None,
+                connector_response_reference_id: item
+                    .response
+                    .data
+                    .order_id
+                    .or(Some(item.response.data.id)),
             }),
             ..item.data
         })
@@ -152,11 +191,13 @@ pub struct BitpayRefundRequest {
     pub amount: i64,
 }
 
-impl<F> TryFrom<&types::RefundsRouterData<F>> for BitpayRefundRequest {
+impl<F> TryFrom<&BitpayRouterData<&types::RefundsRouterData<F>>> for BitpayRefundRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
+    fn try_from(
+        item: &BitpayRouterData<&types::RefundsRouterData<F>>,
+    ) -> Result<Self, Self::Error> {
         Ok(Self {
-            amount: item.request.refund_amount,
+            amount: item.router_data.request.refund_amount,
         })
     }
 }
@@ -232,18 +273,19 @@ pub struct BitpayErrorResponse {
 }
 
 fn get_crypto_specific_payment_data(
-    item: &types::PaymentsAuthorizeRouterData,
+    item: &BitpayRouterData<&types::PaymentsAuthorizeRouterData>,
 ) -> Result<BitpayPaymentsRequest, error_stack::Report<errors::ConnectorError>> {
-    let price = item.request.amount;
-    let currency = item.request.currency.to_string();
-    let redirect_url = item.request.get_return_url()?;
-    let notification_url = item.request.get_webhook_url()?;
+    let price = item.amount;
+    let currency = item.router_data.request.currency.to_string();
+    let redirect_url = item.router_data.request.get_return_url()?;
+    let notification_url = item.router_data.request.get_webhook_url()?;
     let transaction_speed = TransactionSpeed::Medium;
-    let auth_type = item.connector_auth_type.clone();
+    let auth_type = item.router_data.connector_auth_type.clone();
     let token = match auth_type {
         ConnectorAuthType::HeaderKey { api_key } => api_key,
         _ => String::default().into(),
     };
+    let order_id = item.router_data.connector_request_reference_id.clone();
 
     Ok(BitpayPaymentsRequest {
         price,
@@ -252,6 +294,7 @@ fn get_crypto_specific_payment_data(
         notification_url,
         transaction_speed,
         token,
+        order_id,
     })
 }
 
diff --git a/crates/router/src/connector/bluesnap.rs b/crates/router/src/connector/bluesnap.rs
index 24d5787aa8d8..7bd2ce052538 100644
--- a/crates/router/src/connector/bluesnap.rs
+++ b/crates/router/src/connector/bluesnap.rs
@@ -37,6 +37,8 @@ use crate::{
     utils::{self, BytesExt},
 };
 
+pub const BLUESNAP_TRANSACTION_NOT_FOUND: &str = "is not authorized to view merchant-transaction:";
+
 #[derive(Debug, Clone)]
 pub struct Bluesnap;
 
@@ -124,6 +126,7 @@ impl ConnectorCommon for Bluesnap {
                         .map(|error_code_message| error_code_message.error_message)
                         .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
                     reason: Some(reason),
+                    attempt_status: None,
                 }
             }
             bluesnap::BluesnapErrors::Auth(error_res) => ErrorResponse {
@@ -131,13 +134,30 @@ impl ConnectorCommon for Bluesnap {
                 code: error_res.error_code.clone(),
                 message: error_res.error_name.clone().unwrap_or(error_res.error_code),
                 reason: Some(error_res.error_description),
+                attempt_status: None,
             },
-            bluesnap::BluesnapErrors::General(error_response) => ErrorResponse {
-                status_code: res.status_code,
-                code: consts::NO_ERROR_CODE.to_string(),
-                message: error_response.clone(),
-                reason: Some(error_response),
-            },
+            bluesnap::BluesnapErrors::General(error_response) => {
+                let (error_res, attempt_status) = if res.status_code == 403
+                    && error_response.contains(BLUESNAP_TRANSACTION_NOT_FOUND)
+                {
+                    (
+                        format!(
+                            "{} in bluesnap dashboard",
+                            consts::REQUEST_TIMEOUT_PAYMENT_NOT_FOUND
+                        ),
+                        Some(enums::AttemptStatus::Failure), // when bluesnap throws 403 for payment not found, we update the payment status to failure.
+                    )
+                } else {
+                    (error_response.clone(), None)
+                };
+                ErrorResponse {
+                    status_code: res.status_code,
+                    code: consts::NO_ERROR_CODE.to_string(),
+                    message: error_response,
+                    reason: Some(error_res),
+                    attempt_status,
+                }
+            }
         };
         Ok(response_error_message)
     }
@@ -243,6 +263,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = bluesnap::BluesnapVoidRequest::try_from(req)?;
         let bluesnap_req = types::RequestBody::log_and_get_request_body(
@@ -263,7 +284,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
             .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
             .attach_default_headers()
             .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-            .body(types::PaymentsVoidType::get_request_body(self, req)?)
+            .body(types::PaymentsVoidType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -322,21 +345,26 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
         req: &types::PaymentsSyncRouterData,
         connectors: &settings::Connectors,
     ) -> CustomResult<String, errors::ConnectorError> {
-        let meta_data: CustomResult<bluesnap::BluesnapConnectorMetaData, errors::ConnectorError> =
-            connector_utils::to_connector_meta_from_secret(req.connector_meta_data.clone());
-
-        match meta_data {
-            // if merchant_id is present, psync can be made using merchant_transaction_id
-            Ok(data) => get_url_with_merchant_transaction_id(
-                self.base_url(connectors).to_string(),
-                data.merchant_id,
-                req.attempt_id.to_owned(),
-            ),
-            // otherwise psync is made using connector_transaction_id
-            Err(_) => get_psync_url_with_connector_transaction_id(
-                &req.request.connector_transaction_id,
-                self.base_url(connectors).to_string(),
-            ),
+        let connector_transaction_id = req.request.connector_transaction_id.clone();
+        match connector_transaction_id {
+            // if connector_transaction_id is present, we always sync with connector_transaction_id
+            types::ResponseId::ConnectorTransactionId(trans_id) => {
+                get_psync_url_with_connector_transaction_id(
+                    trans_id,
+                    self.base_url(connectors).to_string(),
+                )
+            }
+            _ => {
+                // if connector_transaction_id is not present, we sync with merchant_transaction_id
+                let meta_data: bluesnap::BluesnapConnectorMetaData =
+                    connector_utils::to_connector_meta_from_secret(req.connector_meta_data.clone())
+                        .change_context(errors::ConnectorError::ResponseHandlingFailed)?;
+                get_url_with_merchant_transaction_id(
+                    self.base_url(connectors).to_string(),
+                    meta_data.merchant_id,
+                    req.attempt_id.to_owned(),
+                )
+            }
         }
     }
 
@@ -412,6 +440,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = bluesnap::BluesnapRouterData::try_from((
             &self.get_currency_unit(),
@@ -440,7 +469,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
             .headers(types::PaymentsCaptureType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+            .body(types::PaymentsCaptureType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -504,6 +535,7 @@ impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsSessionRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = bluesnap::BluesnapCreateWalletToken::try_from(req)?;
         let bluesnap_req = types::RequestBody::log_and_get_request_body(
@@ -527,7 +559,9 @@ impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::Payme
                 .headers(types::PaymentsSessionType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsSessionType::get_request_body(self, req)?)
+                .body(types::PaymentsSessionType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -597,6 +631,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = bluesnap::BluesnapRouterData::try_from((
             &self.get_currency_unit(),
@@ -643,7 +678,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -732,6 +769,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCompleteAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = bluesnap::BluesnapRouterData::try_from((
             &self.get_currency_unit(),
@@ -764,7 +802,7 @@ impl
                     self, req, connectors,
                 )?)
                 .body(types::PaymentsCompleteAuthorizeType::get_request_body(
-                    self, req,
+                    self, req, connectors,
                 )?)
                 .build(),
         ))
@@ -830,6 +868,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = bluesnap::BluesnapRouterData::try_from((
             &self.get_currency_unit(),
@@ -858,7 +897,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -1269,12 +1310,9 @@ fn get_url_with_merchant_transaction_id(
 }
 
 fn get_psync_url_with_connector_transaction_id(
-    connector_transaction_id: &types::ResponseId,
+    connector_transaction_id: String,
     base_url: String,
 ) -> CustomResult<String, errors::ConnectorError> {
-    let connector_transaction_id = connector_transaction_id
-        .get_connector_transaction_id()
-        .change_context(errors::ConnectorError::MissingConnectorTransactionID)?;
     Ok(format!(
         "{}{}{}",
         base_url, "services/2/transactions/", connector_transaction_id
diff --git a/crates/router/src/connector/boku.rs b/crates/router/src/connector/boku.rs
index 826d218cd56e..7c2c1af0986b 100644
--- a/crates/router/src/connector/boku.rs
+++ b/crates/router/src/connector/boku.rs
@@ -130,6 +130,7 @@ impl ConnectorCommon for Boku {
                 code: response.code,
                 message: response.message,
                 reason: response.reason,
+                attempt_status: None,
             }),
             Err(_) => get_xml_deserialized(res),
         }
@@ -206,6 +207,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = boku::BokuPaymentsRequest::try_from(req)?;
         let boku_req = types::RequestBody::log_and_get_request_body(
@@ -231,7 +233,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -296,6 +300,7 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
     fn get_request_body(
         &self,
         req: &types::PaymentsSyncRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = boku::BokuPsyncRequest::try_from(req)?;
         let boku_req = types::RequestBody::log_and_get_request_body(
@@ -317,7 +322,9 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
                 .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsSyncType::get_request_body(self, req)?)
+                .body(types::PaymentsSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -377,6 +384,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         _req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into())
     }
@@ -394,7 +402,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -462,6 +472,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = boku::BokuRefundRequest::try_from(req)?;
         let boku_req = types::RequestBody::log_and_get_request_body(
@@ -484,7 +495,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -542,6 +555,7 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
     fn get_request_body(
         &self,
         req: &types::RefundSyncRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = boku::BokuRsyncRequest::try_from(req)?;
         let boku_req = types::RequestBody::log_and_get_request_body(
@@ -563,7 +577,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -651,6 +667,7 @@ fn get_xml_deserialized(res: Response) -> CustomResult<ErrorResponse, errors::Co
                 code: consts::NO_ERROR_CODE.to_string(),
                 message: consts::UNSUPPORTED_ERROR_MESSAGE.to_string(),
                 reason: Some(response_data),
+                attempt_status: None,
             })
         }
     }
diff --git a/crates/router/src/connector/braintree.rs b/crates/router/src/connector/braintree.rs
index 06504e4a9763..6f5b13890367 100644
--- a/crates/router/src/connector/braintree.rs
+++ b/crates/router/src/connector/braintree.rs
@@ -132,6 +132,7 @@ impl ConnectorCommon for Braintree {
                     code,
                     message,
                     reason: Some(response.api_error_response.message),
+                    attempt_status: None,
                 })
             }
             Ok(braintree::ErrorResponse::BraintreeErrorResponse(response)) => Ok(ErrorResponse {
@@ -139,6 +140,7 @@ impl ConnectorCommon for Braintree {
                 code: consts::NO_ERROR_CODE.to_string(),
                 message: consts::NO_ERROR_MESSAGE.to_string(),
                 reason: Some(response.errors),
+                attempt_status: None,
             }),
             Err(error_msg) => {
                 logger::error!(deserialization_error =? error_msg);
@@ -240,7 +242,9 @@ impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::Payme
                         .headers(types::PaymentsSessionType::get_headers(
                             self, req, connectors,
                         )?)
-                        .body(types::PaymentsSessionType::get_request_body(self, req)?)
+                        .body(types::PaymentsSessionType::get_request_body(
+                            self, req, connectors,
+                        )?)
                         .build(),
                 );
                 Ok(request)
@@ -258,6 +262,7 @@ impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsSessionRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = braintree::BraintreeSessionRequest::try_from(req)?;
         let braintree_session_request = types::RequestBody::log_and_get_request_body(
@@ -322,6 +327,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::TokenizationRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request =
             braintree_graphql_transformers::BraintreeTokenRequest::try_from(req)?;
@@ -347,7 +353,9 @@ impl
                     .url(&types::TokenizationType::get_url(self, req, connectors)?)
                     .attach_default_headers()
                     .headers(types::TokenizationType::get_headers(self, req, connectors)?)
-                    .body(types::TokenizationType::get_request_body(self, req)?)
+                    .body(types::TokenizationType::get_request_body(
+                        self, req, connectors,
+                    )?)
                     .build(),
             )),
             false => Ok(None),
@@ -437,6 +445,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_api_version = &req.connector_api_version.clone();
         let connector_router_data =
@@ -482,7 +491,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                     .headers(types::PaymentsCaptureType::get_headers(
                         self, req, connectors,
                     )?)
-                    .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                    .body(types::PaymentsCaptureType::get_request_body(
+                        self, req, connectors,
+                    )?)
                     .build(),
             )),
             false => Err(errors::ConnectorError::NotImplemented(
@@ -587,6 +598,7 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
     fn get_request_body(
         &self,
         req: &types::PaymentsSyncRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_api_version = &req.connector_api_version;
         match self.is_braintree_graphql_version(connector_api_version) {
@@ -618,7 +630,9 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
                     .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                     .attach_default_headers()
                     .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-                    .body(types::PaymentsSyncType::get_request_body(self, req)?)
+                    .body(types::PaymentsSyncType::get_request_body(
+                        self, req, connectors,
+                    )?)
                     .build(),
             )),
             false => Ok(Some(
@@ -627,7 +641,9 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
                     .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                     .attach_default_headers()
                     .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-                    .body(types::PaymentsSyncType::get_request_body(self, req)?)
+                    .body(types::PaymentsSyncType::get_request_body(
+                        self, req, connectors,
+                    )?)
                     .build(),
             )),
         }
@@ -748,7 +764,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -756,6 +774,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_api_version = &req.connector_api_version;
         let connector_router_data =
@@ -918,7 +937,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -926,6 +947,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_api_version = &req.connector_api_version;
         match self.is_braintree_graphql_version(connector_api_version) {
@@ -1055,6 +1077,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_api_version = &req.connector_api_version;
         let connector_router_data =
@@ -1101,7 +1124,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -1189,6 +1214,7 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
     fn get_request_body(
         &self,
         req: &types::RefundSyncRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_api_version = &req.connector_api_version;
         match self.is_braintree_graphql_version(connector_api_version) {
@@ -1219,7 +1245,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                     .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                     .attach_default_headers()
                     .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                    .body(types::RefundSyncType::get_request_body(self, req)?)
+                    .body(types::RefundSyncType::get_request_body(
+                        self, req, connectors,
+                    )?)
                     .build(),
             )),
             false => Ok(None),
@@ -1584,6 +1612,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCompleteAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data =
             braintree_graphql_transformers::BraintreeRouterData::try_from((
@@ -1629,7 +1658,7 @@ impl
                         self, req, connectors,
                     )?)
                     .body(types::PaymentsCompleteAuthorizeType::get_request_body(
-                        self, req,
+                        self, req, connectors,
                     )?)
                     .build(),
             )),
diff --git a/crates/router/src/connector/braintree/braintree_graphql_transformers.rs b/crates/router/src/connector/braintree/braintree_graphql_transformers.rs
index b622e041915d..bf51973237c5 100644
--- a/crates/router/src/connector/braintree/braintree_graphql_transformers.rs
+++ b/crates/router/src/connector/braintree/braintree_graphql_transformers.rs
@@ -316,6 +316,7 @@ fn get_error_response<T>(
         message: error_msg.unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
         reason: error_reason,
         status_code: http_code,
+        attempt_status: None,
     })
 }
 
diff --git a/crates/router/src/connector/cashtocode.rs b/crates/router/src/connector/cashtocode.rs
index ed994dca31fc..12a52e485396 100644
--- a/crates/router/src/connector/cashtocode.rs
+++ b/crates/router/src/connector/cashtocode.rs
@@ -119,6 +119,7 @@ impl ConnectorCommon for Cashtocode {
             code: response.error.to_string(),
             message: response.error_description,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -202,6 +203,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = cashtocode::CashtocodePaymentsRequest::try_from(req)?;
         let cashtocode_req = types::RequestBody::log_and_get_request_body(
@@ -227,7 +229,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/cashtocode/transformers.rs b/crates/router/src/connector/cashtocode/transformers.rs
index 4db1bef7e3f2..2caef69db92c 100644
--- a/crates/router/src/connector/cashtocode/transformers.rs
+++ b/crates/router/src/connector/cashtocode/transformers.rs
@@ -217,6 +217,7 @@ impl<F, T>
                     status_code: item.http_code,
                     message: error_data.error_description,
                     reason: None,
+                    attempt_status: None,
                 }),
             ),
             CashtocodePaymentsResponse::CashtoCodeData(response_data) => {
diff --git a/crates/router/src/connector/checkout.rs b/crates/router/src/connector/checkout.rs
index f4cc4ac9640e..f24c08233ed7 100644
--- a/crates/router/src/connector/checkout.rs
+++ b/crates/router/src/connector/checkout.rs
@@ -131,6 +131,7 @@ impl ConnectorCommon for Checkout {
                 .error_codes
                 .map(|errors| errors.join(" & "))
                 .or(response.error_type),
+            attempt_status: None,
         })
     }
 }
@@ -207,6 +208,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::TokenizationRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = checkout::TokenRequest::try_from(req)?;
         let checkout_req = types::RequestBody::log_and_get_request_body(
@@ -228,7 +230,9 @@ impl
                 .url(&types::TokenizationType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::TokenizationType::get_headers(self, req, connectors)?)
-                .body(types::TokenizationType::get_request_body(self, req)?)
+                .body(types::TokenizationType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -312,6 +316,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = checkout::CheckoutRouterData::try_from((
             &self.get_currency_unit(),
@@ -341,7 +346,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -416,7 +423,9 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
                 .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsSyncType::get_request_body(self, req)?)
+                .body(types::PaymentsSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -497,6 +506,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = checkout::CheckoutRouterData::try_from((
             &self.get_currency_unit(),
@@ -531,7 +541,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -588,6 +600,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = checkout::PaymentVoidRequest::try_from(req)?;
         let checkout_req = types::RequestBody::log_and_get_request_body(
@@ -608,7 +621,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -675,6 +690,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = checkout::CheckoutRouterData::try_from((
             &self.get_currency_unit(),
@@ -703,7 +719,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -772,7 +790,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -1042,6 +1062,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::SubmitEvidenceRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let checkout_req = checkout::Evidence::try_from(req)?;
         let checkout_req_string = types::RequestBody::log_and_get_request_body(
@@ -1064,7 +1085,9 @@ impl
             .headers(types::SubmitEvidenceType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::SubmitEvidenceType::get_request_body(self, req)?)
+            .body(types::SubmitEvidenceType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/checkout/transformers.rs b/crates/router/src/connector/checkout/transformers.rs
index 53182e65ed5b..6ad040da2842 100644
--- a/crates/router/src/connector/checkout/transformers.rs
+++ b/crates/router/src/connector/checkout/transformers.rs
@@ -576,6 +576,7 @@ impl TryFrom<types::PaymentsResponseRouterData<PaymentsResponse>>
                     .clone()
                     .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
                 reason: item.response.response_summary,
+                attempt_status: None,
             })
         } else {
             None
@@ -623,6 +624,7 @@ impl TryFrom<types::PaymentsSyncResponseRouterData<PaymentsResponse>>
                     .clone()
                     .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
                 reason: item.response.response_summary,
+                attempt_status: None,
             })
         } else {
             None
diff --git a/crates/router/src/connector/coinbase.rs b/crates/router/src/connector/coinbase.rs
index d50e490cfc30..5704ea15b005 100644
--- a/crates/router/src/connector/coinbase.rs
+++ b/crates/router/src/connector/coinbase.rs
@@ -108,6 +108,7 @@ impl ConnectorCommon for Coinbase {
             code: response.error.error_type,
             message: response.error.message,
             reason: response.error.code,
+            attempt_status: None,
         })
     }
 }
@@ -183,6 +184,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = coinbase::CoinbasePaymentsRequest::try_from(req)?;
         let coinbase_payment_request = types::RequestBody::log_and_get_request_body(
@@ -207,7 +209,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/cryptopay.rs b/crates/router/src/connector/cryptopay.rs
index 7e1b334b3619..d2d8fa0f1ec2 100644
--- a/crates/router/src/connector/cryptopay.rs
+++ b/crates/router/src/connector/cryptopay.rs
@@ -69,7 +69,7 @@ where
         connectors: &settings::Connectors,
     ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
         let api_method;
-        let payload = match self.get_request_body(req)? {
+        let payload = match self.get_request_body(req, connectors)? {
             Some(val) => {
                 let body = types::RequestBody::get_inner_value(val).peek().to_owned();
                 api_method = "POST".to_string();
@@ -167,12 +167,11 @@ impl ConnectorCommon for Cryptopay {
             code: response.error.code,
             message: response.error.message,
             reason: response.error.reason,
+            attempt_status: None,
         })
     }
 }
 
-impl ConnectorValidation for Cryptopay {}
-
 impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::PaymentsResponseData>
     for Cryptopay
 {
@@ -218,6 +217,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = cryptopay::CryptopayRouterData::try_from((
             &self.get_currency_unit(),
@@ -250,7 +250,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -279,6 +281,16 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     }
 }
 
+impl ConnectorValidation for Cryptopay {
+    fn validate_psync_reference_id(
+        &self,
+        _data: &types::PaymentsSyncRouterData,
+    ) -> CustomResult<(), errors::ConnectorError> {
+        // since we can make psync call with our reference_id, having connector_transaction_id is not an mandatory criteria
+        Ok(())
+    }
+}
+
 impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
     for Cryptopay
 {
diff --git a/crates/router/src/connector/cryptopay/transformers.rs b/crates/router/src/connector/cryptopay/transformers.rs
index a49380cb3656..0bc4ff3b3ae6 100644
--- a/crates/router/src/connector/cryptopay/transformers.rs
+++ b/crates/router/src/connector/cryptopay/transformers.rs
@@ -69,9 +69,23 @@ impl TryFrom<&CryptopayRouterData<&types::PaymentsAuthorizeRouterData>>
                     custom_id: item.router_data.connector_request_reference_id.clone(),
                 })
             }
-            _ => Err(errors::ConnectorError::NotImplemented(
-                "payment method".to_string(),
-            )),
+            api_models::payments::PaymentMethodData::Card(_)
+            | api_models::payments::PaymentMethodData::CardRedirect(_)
+            | api_models::payments::PaymentMethodData::Wallet(_)
+            | api_models::payments::PaymentMethodData::PayLater(_)
+            | api_models::payments::PaymentMethodData::BankRedirect(_)
+            | api_models::payments::PaymentMethodData::BankDebit(_)
+            | api_models::payments::PaymentMethodData::BankTransfer(_)
+            | api_models::payments::PaymentMethodData::MandatePayment {}
+            | api_models::payments::PaymentMethodData::Reward {}
+            | api_models::payments::PaymentMethodData::Upi(_)
+            | api_models::payments::PaymentMethodData::Voucher(_)
+            | api_models::payments::PaymentMethodData::GiftCard(_) => {
+                Err(errors::ConnectorError::NotSupported {
+                    message: utils::SELECTED_PAYMENT_METHOD.to_string(),
+                    connector: "CryptoPay",
+                })
+            }
         }?;
         Ok(cryptopay_request)
     }
@@ -97,10 +111,9 @@ impl TryFrom<&types::ConnectorAuthType> for CryptopayAuthType {
     }
 }
 // PaymentsResponse
-#[derive(Debug, Clone, Default, Serialize, Deserialize)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
 #[serde(rename_all = "lowercase")]
 pub enum CryptopayPaymentStatus {
-    #[default]
     New,
     Completed,
     Unresolved,
@@ -114,13 +127,14 @@ impl From<CryptopayPaymentStatus> for enums::AttemptStatus {
             CryptopayPaymentStatus::New => Self::AuthenticationPending,
             CryptopayPaymentStatus::Completed => Self::Charged,
             CryptopayPaymentStatus::Cancelled => Self::Failure,
-            CryptopayPaymentStatus::Unresolved => Self::Unresolved,
-            _ => Self::Voided,
+            CryptopayPaymentStatus::Unresolved | CryptopayPaymentStatus::Refunded => {
+                Self::Unresolved
+            } //mapped refunded to Unresolved because refund api is not available, also merchant has done the action on the connector dashboard.
         }
     }
 }
 
-#[derive(Default, Debug, Serialize, Deserialize)]
+#[derive(Debug, Serialize, Deserialize)]
 pub struct CryptopayPaymentsResponse {
     data: CryptopayPaymentResponseData,
 }
@@ -176,7 +190,7 @@ pub struct CryptopayErrorResponse {
     pub error: CryptopayErrorData,
 }
 
-#[derive(Debug, Default, Serialize, Deserialize)]
+#[derive(Debug, Serialize, Deserialize)]
 pub struct CryptopayPaymentResponseData {
     pub id: String,
     pub custom_id: Option<String>,
diff --git a/crates/router/src/connector/cybersource.rs b/crates/router/src/connector/cybersource.rs
index d1ad36b26d1e..ee6e93aebbd0 100644
--- a/crates/router/src/connector/cybersource.rs
+++ b/crates/router/src/connector/cybersource.rs
@@ -93,6 +93,10 @@ impl ConnectorCommon for Cybersource {
         connectors.cybersource.base_url.as_ref()
     }
 
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Minor
+    }
+
     fn build_error_response(
         &self,
         res: types::Response,
@@ -132,6 +136,7 @@ impl ConnectorCommon for Cybersource {
             code,
             message,
             reason: Some(connector_reason),
+            attempt_status: None,
         })
     }
 }
@@ -162,7 +167,7 @@ where
     ) -> CustomResult<Vec<(String, services::request::Maskable<String>)>, errors::ConnectorError>
     {
         let date = OffsetDateTime::now_utc();
-        let cybersource_req = self.get_request_body(req)?;
+        let cybersource_req = self.get_request_body(req, connectors)?;
         let auth = cybersource::CybersourceAuthType::try_from(&req.connector_auth_type)?;
         let merchant_account = auth.merchant_account.clone();
         let base_url = connectors.cybersource.base_url.as_str();
@@ -293,6 +298,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = cybersource::CybersourcePaymentsRequest::try_from(req)?;
         let cybersource_payments_request = types::RequestBody::log_and_get_request_body(
@@ -315,7 +321,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -389,6 +397,7 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
     fn get_request_body(
         &self,
         _req: &types::PaymentsSyncRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         Ok(Some(
             types::RequestBody::log_and_get_request_body("{}".to_string(), Ok)
@@ -467,8 +476,16 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let connector_request = cybersource::CybersourcePaymentsRequest::try_from(req)?;
+        let connector_router_data = cybersource::CybersourceRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+        let connector_request =
+            cybersource::CybersourcePaymentsRequest::try_from(&connector_router_data)?;
         let cybersource_payments_request = types::RequestBody::log_and_get_request_body(
             &connector_request,
             utils::Encode::<cybersource::CybersourcePaymentsRequest>::encode_to_string_of_json,
@@ -491,7 +508,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
             .headers(types::PaymentsAuthorizeType::get_headers(
                 self, req, connectors,
             )?)
-            .body(self.get_request_body(req)?)
+            .body(self.get_request_body(req, connectors)?)
             .build();
 
         Ok(Some(request))
@@ -558,6 +575,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         _req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         Ok(Some(
             types::RequestBody::log_and_get_request_body("{}".to_string(), Ok)
@@ -576,7 +594,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(self.get_request_body(req)?)
+                .body(self.get_request_body(req, connectors)?)
                 .build(),
         ))
     }
@@ -645,6 +663,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundExecuteRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = cybersource::CybersourceRefundRequest::try_from(req)?;
         let cybersource_refund_request = types::RequestBody::log_and_get_request_body(
@@ -667,7 +686,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
                 .headers(types::RefundExecuteType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(self.get_request_body(req)?)
+                .body(self.get_request_body(req, connectors)?)
                 .build(),
         ))
     }
@@ -736,7 +755,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs
index 5a3060f99ebd..9233a95d7dd7 100644
--- a/crates/router/src/connector/cybersource/transformers.rs
+++ b/crates/router/src/connector/cybersource/transformers.rs
@@ -15,6 +15,37 @@ use crate::{
     },
 };
 
+#[derive(Debug, Serialize)]
+pub struct CybersourceRouterData<T> {
+    pub amount: String,
+    pub router_data: T,
+}
+
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for CybersourceRouterData<T>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        (currency_unit, currency, amount, item): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        let amount = utils::get_amount_as_string(currency_unit, amount, currency)?;
+        Ok(Self {
+            amount,
+            router_data: item,
+        })
+    }
+}
+
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 #[serde(rename_all = "camelCase")]
 pub struct CybersourcePaymentsRequest {
@@ -109,27 +140,33 @@ fn build_bill_to(
     })
 }
 
-impl TryFrom<&types::PaymentsAuthorizeRouterData> for CybersourcePaymentsRequest {
+impl TryFrom<&CybersourceRouterData<&types::PaymentsAuthorizeRouterData>>
+    for CybersourcePaymentsRequest
+{
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
-        match item.request.payment_method_data.clone() {
+    fn try_from(
+        item: &CybersourceRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
+        match item.router_data.request.payment_method_data.clone() {
             api::PaymentMethodData::Card(ccard) => {
-                let phone = item.get_billing_phone()?;
+                let phone = item.router_data.get_billing_phone()?;
                 let phone_number = phone.get_number()?;
                 let country_code = phone.get_country_code()?;
                 let number_with_code =
                     Secret::new(format!("{}{}", country_code, phone_number.peek()));
                 let email = item
+                    .router_data
                     .request
                     .email
                     .clone()
                     .ok_or_else(utils::missing_field_err("email"))?;
-                let bill_to = build_bill_to(item.get_billing()?, email, number_with_code)?;
+                let bill_to =
+                    build_bill_to(item.router_data.get_billing()?, email, number_with_code)?;
 
                 let order_information = OrderInformationWithBill {
                     amount_details: Amount {
-                        total_amount: item.request.amount.to_string(),
-                        currency: item.request.currency.to_string().to_uppercase(),
+                        total_amount: item.amount.to_owned(),
+                        currency: item.router_data.request.currency.to_string().to_uppercase(),
                     },
                     bill_to,
                 };
@@ -145,14 +182,14 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for CybersourcePaymentsRequest
 
                 let processing_information = ProcessingInformation {
                     capture: matches!(
-                        item.request.capture_method,
+                        item.router_data.request.capture_method,
                         Some(enums::CaptureMethod::Automatic) | None
                     ),
                     capture_options: None,
                 };
 
                 let client_reference_information = ClientReferenceInformation {
-                    code: Some(item.connector_request_reference_id.clone()),
+                    code: Some(item.router_data.connector_request_reference_id.clone()),
                 };
 
                 Ok(Self {
@@ -330,6 +367,7 @@ impl<F, T>
                     message: error.message,
                     reason: Some(error.reason),
                     status_code: item.http_code,
+                    attempt_status: None,
                 }),
                 _ => Ok(types::PaymentsResponseData::TransactionResponse {
                     resource_id: types::ResponseId::ConnectorTransactionId(
diff --git a/crates/router/src/connector/dlocal.rs b/crates/router/src/connector/dlocal.rs
index b706d694a3d5..64d3e6f1c12f 100644
--- a/crates/router/src/connector/dlocal.rs
+++ b/crates/router/src/connector/dlocal.rs
@@ -53,10 +53,10 @@ where
     fn build_headers(
         &self,
         req: &types::RouterData<Flow, Request, Response>,
-        _connectors: &settings::Connectors,
+        connectors: &settings::Connectors,
     ) -> CustomResult<Vec<(String, services::request::Maskable<String>)>, errors::ConnectorError>
     {
-        let dlocal_req = match self.get_request_body(req)? {
+        let dlocal_req = match self.get_request_body(req, connectors)? {
             Some(val) => val,
             None => types::RequestBody::log_and_get_request_body("".to_string(), Ok)
                 .change_context(errors::ConnectorError::RequestEncodingFailed)?,
@@ -135,6 +135,7 @@ impl ConnectorCommon for Dlocal {
             code: response.code.to_string(),
             message: response.message,
             reason: response.param,
+            attempt_status: None,
         })
     }
 }
@@ -210,6 +211,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = dlocal::DlocalRouterData::try_from((
             &self.get_currency_unit(),
@@ -241,7 +243,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -368,6 +372,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = dlocal::DlocalPaymentsCaptureRequest::try_from(req)?;
         let dlocal_payments_capture_request = types::RequestBody::log_and_get_request_body(
@@ -391,7 +396,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -517,6 +524,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = dlocal::DlocalRouterData::try_from((
             &self.get_currency_unit(),
@@ -545,7 +553,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/dlocal/transformers.rs b/crates/router/src/connector/dlocal/transformers.rs
index 87562fa33448..668a335cce88 100644
--- a/crates/router/src/connector/dlocal/transformers.rs
+++ b/crates/router/src/connector/dlocal/transformers.rs
@@ -145,7 +145,7 @@ impl TryFrom<&DlocalRouterData<&types::PaymentsAuthorizeRouterData>> for DlocalP
                             .clone()
                             .map(|_| "1".to_string()),
                     }),
-                    order_id: item.router_data.payment_id.clone(),
+                    order_id: item.router_data.connector_request_reference_id.clone(),
                     three_dsecure: match item.router_data.auth_type {
                         diesel_models::enums::AuthenticationType::ThreeDs => {
                             Some(ThreeDSecureReqData { force: true })
@@ -157,7 +157,20 @@ impl TryFrom<&DlocalRouterData<&types::PaymentsAuthorizeRouterData>> for DlocalP
                 };
                 Ok(payment_request)
             }
-            _ => Err(errors::ConnectorError::NotImplemented("Payment Method".to_string()).into()),
+            api::PaymentMethodData::CardRedirect(_)
+            | api::PaymentMethodData::Wallet(_)
+            | api::PaymentMethodData::PayLater(_)
+            | api::PaymentMethodData::BankRedirect(_)
+            | api::PaymentMethodData::BankDebit(_)
+            | api::PaymentMethodData::BankTransfer(_)
+            | api::PaymentMethodData::Crypto(_)
+            | api::PaymentMethodData::MandatePayment
+            | api::PaymentMethodData::Reward
+            | api::PaymentMethodData::Upi(_)
+            | api::PaymentMethodData::Voucher(_)
+            | api::PaymentMethodData::GiftCard(_) => Err(errors::ConnectorError::NotImplemented(
+                crate::connector::utils::get_unimplemented_payment_method_error_message("Dlocal"),
+            ))?,
         }
     }
 }
@@ -224,7 +237,7 @@ impl TryFrom<&types::PaymentsCaptureRouterData> for DlocalPaymentsCaptureRequest
             authorization_id: item.request.connector_transaction_id.clone(),
             amount: item.request.amount_to_capture,
             currency: item.request.currency.to_string(),
-            order_id: item.payment_id.clone(),
+            order_id: item.connector_request_reference_id.clone(),
         })
     }
 }
diff --git a/crates/router/src/connector/dummyconnector.rs b/crates/router/src/connector/dummyconnector.rs
index af87029a682c..b501936b8713 100644
--- a/crates/router/src/connector/dummyconnector.rs
+++ b/crates/router/src/connector/dummyconnector.rs
@@ -111,6 +111,7 @@ impl<const T: u8> ConnectorCommon for DummyConnector<T> {
             code: response.error.code,
             message: response.error.message,
             reason: response.error.reason,
+            attempt_status: None,
         })
     }
 }
@@ -187,6 +188,7 @@ impl<const T: u8>
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = transformers::DummyConnectorPaymentsRequest::<T>::try_from(req)?;
         let dummmy_payments_request = types::RequestBody::log_and_get_request_body(
@@ -212,7 +214,9 @@ impl<const T: u8>
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -347,6 +351,7 @@ impl<const T: u8>
     fn get_request_body(
         &self,
         _req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into())
     }
@@ -429,6 +434,7 @@ impl<const T: u8> ConnectorIntegration<api::Execute, types::RefundsData, types::
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = transformers::DummyConnectorRefundRequest::try_from(req)?;
         let dummmy_refund_request = types::RequestBody::log_and_get_request_body(
@@ -451,7 +457,9 @@ impl<const T: u8> ConnectorIntegration<api::Execute, types::RefundsData, types::
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -520,7 +528,9 @@ impl<const T: u8> ConnectorIntegration<api::RSync, types::RefundsData, types::Re
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/fiserv.rs b/crates/router/src/connector/fiserv.rs
index 70f58ffe6eb0..093f71b3da14 100644
--- a/crates/router/src/connector/fiserv.rs
+++ b/crates/router/src/connector/fiserv.rs
@@ -62,7 +62,7 @@ where
     fn build_headers(
         &self,
         req: &types::RouterData<Flow, Request, Response>,
-        _connectors: &settings::Connectors,
+        connectors: &settings::Connectors,
     ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
         let timestamp = OffsetDateTime::now_utc().unix_timestamp_nanos() / 1_000_000;
         let auth: fiserv::FiservAuthType =
@@ -70,7 +70,7 @@ where
         let mut auth_header = self.get_auth_header(&req.connector_auth_type)?;
 
         let fiserv_req = self
-            .get_request_body(req)?
+            .get_request_body(req, connectors)?
             .ok_or(errors::ConnectorError::RequestEncodingFailed)?;
 
         let client_request_id = Uuid::new_v4().to_string();
@@ -104,6 +104,10 @@ impl ConnectorCommon for Fiserv {
         "fiserv"
     }
 
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Base
+    }
+
     fn common_get_content_type(&self) -> &'static str {
         "application/json"
     }
@@ -147,6 +151,7 @@ impl ConnectorCommon for Fiserv {
                         message: first_error.message.to_owned(),
                         reason: first_error.field.to_owned(),
                         status_code: res.status_code,
+                        attempt_status: None,
                     })
             })
             .unwrap_or(types::ErrorResponse {
@@ -154,6 +159,7 @@ impl ConnectorCommon for Fiserv {
                 message: consts::NO_ERROR_MESSAGE.to_string(),
                 reason: None,
                 status_code: res.status_code,
+                attempt_status: None,
             }))
     }
 }
@@ -240,6 +246,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = fiserv::FiservCancelRequest::try_from(req)?;
         let fiserv_payments_cancel_request = types::RequestBody::log_and_get_request_body(
@@ -261,7 +268,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         );
 
@@ -326,6 +335,7 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
     fn get_request_body(
         &self,
         req: &types::PaymentsSyncRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = fiserv::FiservSyncRequest::try_from(req)?;
         let fiserv_payments_sync_request = types::RequestBody::log_and_get_request_body(
@@ -347,7 +357,9 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
                 .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsSyncType::get_request_body(self, req)?)
+                .body(types::PaymentsSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         );
         Ok(request)
@@ -399,8 +411,15 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let connector_request = fiserv::FiservCaptureRequest::try_from(req)?;
+        let router_obj = fiserv::FiservRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount_to_capture,
+            req,
+        ))?;
+        let connector_request = fiserv::FiservCaptureRequest::try_from(&router_obj)?;
         let fiserv_payments_capture_request = types::RequestBody::log_and_get_request_body(
             &connector_request,
             utils::Encode::<fiserv::FiservCaptureRequest>::encode_to_string_of_json,
@@ -422,7 +441,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         );
         Ok(request)
@@ -504,8 +525,15 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let connector_request = fiserv::FiservPaymentsRequest::try_from(req)?;
+        let router_obj = fiserv::FiservRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+        let connector_request = fiserv::FiservPaymentsRequest::try_from(&router_obj)?;
         let fiserv_payments_request = types::RequestBody::log_and_get_request_body(
             &connector_request,
             utils::Encode::<fiserv::FiservPaymentsRequest>::encode_to_string_of_json,
@@ -529,7 +557,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         );
 
@@ -591,8 +621,15 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let connector_request = fiserv::FiservRefundRequest::try_from(req)?;
+        let router_obj = fiserv::FiservRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.refund_amount,
+            req,
+        ))?;
+        let connector_request = fiserv::FiservRefundRequest::try_from(&router_obj)?;
         let fiserv_refund_request = types::RequestBody::log_and_get_request_body(
             &connector_request,
             utils::Encode::<fiserv::FiservRefundRequest>::encode_to_string_of_json,
@@ -612,7 +649,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -671,6 +710,7 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
     fn get_request_body(
         &self,
         req: &types::RefundSyncRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = fiserv::FiservSyncRequest::try_from(req)?;
         let fiserv_sync_request = types::RequestBody::log_and_get_request_body(
@@ -692,7 +732,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         );
         Ok(request)
diff --git a/crates/router/src/connector/fiserv/transformers.rs b/crates/router/src/connector/fiserv/transformers.rs
index c9c2f0c4087a..2d07da7f47a4 100644
--- a/crates/router/src/connector/fiserv/transformers.rs
+++ b/crates/router/src/connector/fiserv/transformers.rs
@@ -9,6 +9,38 @@ use crate::{
     types::{self, api, storage::enums},
 };
 
+#[derive(Debug, Serialize)]
+pub struct FiservRouterData<T> {
+    pub amount: String,
+    pub router_data: T,
+}
+
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for FiservRouterData<T>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+
+    fn try_from(
+        (currency_unit, currency, amount, router_data): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        let amount = utils::get_amount_as_string(currency_unit, amount, currency)?;
+        Ok(Self {
+            amount,
+            router_data,
+        })
+    }
+}
+
 #[derive(Debug, Serialize, Eq, PartialEq)]
 #[serde(rename_all = "camelCase")]
 pub struct FiservPaymentsRequest {
@@ -62,6 +94,7 @@ pub struct Amount {
 pub struct TransactionDetails {
     capture_flag: Option<bool>,
     reversal_reason_code: Option<String>,
+    merchant_transaction_id: String,
 }
 
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
@@ -98,22 +131,25 @@ pub enum TransactionInteractionPosConditionCode {
     CardNotPresentEcom,
 }
 
-impl TryFrom<&types::PaymentsAuthorizeRouterData> for FiservPaymentsRequest {
+impl TryFrom<&FiservRouterData<&types::PaymentsAuthorizeRouterData>> for FiservPaymentsRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
-        let auth: FiservAuthType = FiservAuthType::try_from(&item.connector_auth_type)?;
+    fn try_from(
+        item: &FiservRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
+        let auth: FiservAuthType = FiservAuthType::try_from(&item.router_data.connector_auth_type)?;
         let amount = Amount {
-            total: utils::to_currency_base_unit(item.request.amount, item.request.currency)?,
-            currency: item.request.currency.to_string(),
+            total: item.amount.clone(),
+            currency: item.router_data.request.currency.to_string(),
         };
         let transaction_details = TransactionDetails {
             capture_flag: Some(matches!(
-                item.request.capture_method,
+                item.router_data.request.capture_method,
                 Some(enums::CaptureMethod::Automatic) | None
             )),
             reversal_reason_code: None,
+            merchant_transaction_id: item.router_data.connector_request_reference_id.clone(),
         };
-        let metadata = item.get_connector_meta()?;
+        let metadata = item.router_data.get_connector_meta()?;
         let session: SessionObject = metadata
             .parse_value("SessionObject")
             .change_context(errors::ConnectorError::RequestEncodingFailed)?;
@@ -131,7 +167,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for FiservPaymentsRequest {
             //card not present in online transaction
             pos_condition_code: TransactionInteractionPosConditionCode::CardNotPresentEcom,
         };
-        let source = match item.request.payment_method_data.clone() {
+        let source = match item.router_data.request.payment_method_data.clone() {
             api::PaymentMethodData::Card(ref ccard) => {
                 let card = CardData {
                     card_data: ccard.card_number.clone(),
@@ -208,6 +244,7 @@ impl TryFrom<&types::PaymentsCancelRouterData> for FiservCancelRequest {
             transaction_details: TransactionDetails {
                 capture_flag: None,
                 reversal_reason_code: Some(item.request.get_cancellation_reason()?),
+                merchant_transaction_id: item.connector_request_reference_id.clone(),
             },
         })
     }
@@ -386,34 +423,40 @@ pub struct SessionObject {
     pub terminal_id: String,
 }
 
-impl TryFrom<&types::PaymentsCaptureRouterData> for FiservCaptureRequest {
+impl TryFrom<&FiservRouterData<&types::PaymentsCaptureRouterData>> for FiservCaptureRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsCaptureRouterData) -> Result<Self, Self::Error> {
-        let auth: FiservAuthType = FiservAuthType::try_from(&item.connector_auth_type)?;
+    fn try_from(
+        item: &FiservRouterData<&types::PaymentsCaptureRouterData>,
+    ) -> Result<Self, Self::Error> {
+        let auth: FiservAuthType = FiservAuthType::try_from(&item.router_data.connector_auth_type)?;
         let metadata = item
+            .router_data
             .connector_meta_data
             .clone()
             .ok_or(errors::ConnectorError::RequestEncodingFailed)?;
         let session: SessionObject = metadata
             .parse_value("SessionObject")
             .change_context(errors::ConnectorError::RequestEncodingFailed)?;
-        let amount =
-            utils::to_currency_base_unit(item.request.amount_to_capture, item.request.currency)?;
         Ok(Self {
             amount: Amount {
-                total: amount,
-                currency: item.request.currency.to_string(),
+                total: item.amount.clone(),
+                currency: item.router_data.request.currency.to_string(),
             },
             transaction_details: TransactionDetails {
                 capture_flag: Some(true),
                 reversal_reason_code: None,
+                merchant_transaction_id: item.router_data.connector_request_reference_id.clone(),
             },
             merchant_details: MerchantDetails {
                 merchant_id: auth.merchant_account,
                 terminal_id: Some(session.terminal_id),
             },
             reference_transaction_details: ReferenceTransactionDetails {
-                reference_transaction_id: item.request.connector_transaction_id.to_string(),
+                reference_transaction_id: item
+                    .router_data
+                    .request
+                    .connector_transaction_id
+                    .to_string(),
             },
         })
     }
@@ -473,11 +516,14 @@ pub struct FiservRefundRequest {
     reference_transaction_details: ReferenceTransactionDetails,
 }
 
-impl<F> TryFrom<&types::RefundsRouterData<F>> for FiservRefundRequest {
+impl<F> TryFrom<&FiservRouterData<&types::RefundsRouterData<F>>> for FiservRefundRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
-        let auth: FiservAuthType = FiservAuthType::try_from(&item.connector_auth_type)?;
+    fn try_from(
+        item: &FiservRouterData<&types::RefundsRouterData<F>>,
+    ) -> Result<Self, Self::Error> {
+        let auth: FiservAuthType = FiservAuthType::try_from(&item.router_data.connector_auth_type)?;
         let metadata = item
+            .router_data
             .connector_meta_data
             .clone()
             .ok_or(errors::ConnectorError::RequestEncodingFailed)?;
@@ -486,18 +532,19 @@ impl<F> TryFrom<&types::RefundsRouterData<F>> for FiservRefundRequest {
             .change_context(errors::ConnectorError::RequestEncodingFailed)?;
         Ok(Self {
             amount: Amount {
-                total: utils::to_currency_base_unit(
-                    item.request.refund_amount,
-                    item.request.currency,
-                )?,
-                currency: item.request.currency.to_string(),
+                total: item.amount.clone(),
+                currency: item.router_data.request.currency.to_string(),
             },
             merchant_details: MerchantDetails {
                 merchant_id: auth.merchant_account,
                 terminal_id: Some(session.terminal_id),
             },
             reference_transaction_details: ReferenceTransactionDetails {
-                reference_transaction_id: item.request.connector_transaction_id.to_string(),
+                reference_transaction_id: item
+                    .router_data
+                    .request
+                    .connector_transaction_id
+                    .to_string(),
             },
         })
     }
diff --git a/crates/router/src/connector/forte.rs b/crates/router/src/connector/forte.rs
index 6f20e93e8c8d..40448c01fabf 100644
--- a/crates/router/src/connector/forte.rs
+++ b/crates/router/src/connector/forte.rs
@@ -130,6 +130,7 @@ impl ConnectorCommon for Forte {
             code,
             message,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -200,6 +201,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = forte::FortePaymentsRequest::try_from(req)?;
         let forte_req = types::RequestBody::log_and_get_request_body(
@@ -225,7 +227,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -356,6 +360,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = forte::ForteCaptureRequest::try_from(req)?;
         let forte_req = types::RequestBody::log_and_get_request_body(
@@ -379,7 +384,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -439,6 +446,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = forte::ForteCancelRequest::try_from(req)?;
         let forte_req = types::RequestBody::log_and_get_request_body(
@@ -460,7 +468,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -519,6 +529,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = forte::ForteRefundRequest::try_from(req)?;
         let forte_req = types::RequestBody::log_and_get_request_body(
@@ -541,7 +552,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/forte/transformers.rs b/crates/router/src/connector/forte/transformers.rs
index bc7c55c4f87c..dd78324c9b8b 100644
--- a/crates/router/src/connector/forte/transformers.rs
+++ b/crates/router/src/connector/forte/transformers.rs
@@ -101,9 +101,23 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for FortePaymentsRequest {
                     card,
                 })
             }
-            _ => Err(errors::ConnectorError::NotImplemented(
-                "Payment Method".to_string(),
-            ))?,
+            api_models::payments::PaymentMethodData::CardRedirect(_)
+            | api_models::payments::PaymentMethodData::Wallet(_)
+            | api_models::payments::PaymentMethodData::PayLater(_)
+            | api_models::payments::PaymentMethodData::BankRedirect(_)
+            | api_models::payments::PaymentMethodData::BankDebit(_)
+            | api_models::payments::PaymentMethodData::BankTransfer(_)
+            | api_models::payments::PaymentMethodData::Crypto(_)
+            | api_models::payments::PaymentMethodData::MandatePayment {}
+            | api_models::payments::PaymentMethodData::Reward {}
+            | api_models::payments::PaymentMethodData::Upi(_)
+            | api_models::payments::PaymentMethodData::Voucher(_)
+            | api_models::payments::PaymentMethodData::GiftCard(_) => {
+                Err(errors::ConnectorError::NotSupported {
+                    message: utils::SELECTED_PAYMENT_METHOD.to_string(),
+                    connector: "Forte",
+                })?
+            }
         }
     }
 }
@@ -165,6 +179,7 @@ impl ForeignFrom<(ForteResponseCode, ForteAction)> for enums::AttemptStatus {
             ForteResponseCode::A01 => match action {
                 ForteAction::Authorize => Self::Authorized,
                 ForteAction::Sale => Self::Pending,
+                ForteAction::Verify => Self::Charged,
             },
             ForteResponseCode::A05 | ForteResponseCode::A06 => Self::Authorizing,
             _ => Self::Failure,
@@ -218,6 +233,7 @@ pub struct ResponseStatus {
 pub enum ForteAction {
     Sale,
     Authorize,
+    Verify,
 }
 
 #[derive(Debug, Deserialize)]
diff --git a/crates/router/src/connector/globalpay.rs b/crates/router/src/connector/globalpay.rs
index dfcddae777e8..cfa1349633b2 100644
--- a/crates/router/src/connector/globalpay.rs
+++ b/crates/router/src/connector/globalpay.rs
@@ -104,6 +104,7 @@ impl ConnectorCommon for Globalpay {
             code: response.error_code,
             message: response.detailed_error_description,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -164,6 +165,7 @@ impl
     fn get_request_body(
         &self,
         _req: &types::PaymentsCompleteAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let globalpay_req = types::RequestBody::log_and_get_request_body("{}".to_string(), Ok)
             .change_context(errors::ConnectorError::RequestEncodingFailed)?;
@@ -186,7 +188,7 @@ impl
                     self, req, connectors,
                 )?)
                 .body(types::PaymentsCompleteAuthorizeType::get_request_body(
-                    self, req,
+                    self, req, connectors,
                 )?)
                 .build(),
         ))
@@ -262,7 +264,9 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
                 .url(&types::RefreshTokenType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefreshTokenType::get_headers(self, req, connectors)?)
-                .body(types::RefreshTokenType::get_request_body(self, req)?)
+                .body(types::RefreshTokenType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -270,6 +274,7 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
     fn get_request_body(
         &self,
         req: &types::RefreshTokenRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = GlobalpayRefreshTokenRequest::try_from(req)?;
         let globalpay_req = types::RequestBody::log_and_get_request_body(
@@ -313,6 +318,7 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
             code: response.error_code,
             message: response.detailed_error_description,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -381,7 +387,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -389,6 +397,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = requests::GlobalpayCancelRequest::try_from(req)?;
         let globalpay_req = types::RequestBody::log_and_get_request_body(
@@ -539,6 +548,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = requests::GlobalpayCaptureRequest::try_from(req)?;
         let globalpay_req = types::RequestBody::log_and_get_request_body(
@@ -562,7 +572,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -628,6 +640,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = GlobalpayPaymentsRequest::try_from(req)?;
         let globalpay_req = types::RequestBody::log_and_get_request_body(
@@ -653,7 +666,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -718,6 +733,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = requests::GlobalpayRefundRequest::try_from(req)?;
         let globalpay_req = types::RequestBody::log_and_get_request_body(
@@ -740,7 +756,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -809,7 +827,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/globepay.rs b/crates/router/src/connector/globepay.rs
index c1bda5932834..547bf66fb7d5 100644
--- a/crates/router/src/connector/globepay.rs
+++ b/crates/router/src/connector/globepay.rs
@@ -122,6 +122,7 @@ impl ConnectorCommon for Globepay {
             code: response.return_code.to_string(),
             message: consts::NO_ERROR_MESSAGE.to_string(),
             reason: Some(response.return_msg),
+            attempt_status: None,
         })
     }
 }
@@ -187,6 +188,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = globepay::GlobepayPaymentsRequest::try_from(req)?;
         let globepay_req = types::RequestBody::log_and_get_request_body(
@@ -212,7 +214,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -363,6 +367,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = globepay::GlobepayRefundRequest::try_from(req)?;
         let globepay_req = types::RequestBody::log_and_get_request_body(
@@ -386,7 +391,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
                 .headers(types::RefundExecuteType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::RefundExecuteType::get_request_body(self, req)?)
+                .body(types::RefundExecuteType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/globepay/transformers.rs b/crates/router/src/connector/globepay/transformers.rs
index e78edf3ff47b..1bea602e7401 100644
--- a/crates/router/src/connector/globepay/transformers.rs
+++ b/crates/router/src/connector/globepay/transformers.rs
@@ -257,6 +257,7 @@ fn get_error_response(
         message: consts::NO_ERROR_MESSAGE.to_string(),
         reason: return_msg,
         status_code,
+        attempt_status: None,
     }
 }
 
diff --git a/crates/router/src/connector/gocardless.rs b/crates/router/src/connector/gocardless.rs
index d6e6f30ad9f4..1a6ac8441652 100644
--- a/crates/router/src/connector/gocardless.rs
+++ b/crates/router/src/connector/gocardless.rs
@@ -122,6 +122,7 @@ impl ConnectorCommon for Gocardless {
             code: response.error.code.to_string(),
             message: response.error.error_type,
             reason: Some(error_reason.join("; ")),
+            attempt_status: None,
         })
     }
 }
@@ -152,6 +153,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::ConnectorCustomerRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = gocardless::GocardlessCustomerRequest::try_from(req)?;
         let gocardless_req = types::RequestBody::log_and_get_request_body(
@@ -177,7 +179,9 @@ impl
                 .headers(types::ConnectorCustomerType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::ConnectorCustomerType::get_request_body(self, req)?)
+                .body(types::ConnectorCustomerType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -247,6 +251,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::TokenizationRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = gocardless::GocardlessBankAccountRequest::try_from(req)?;
         let gocardless_req = types::RequestBody::log_and_get_request_body(
@@ -268,7 +273,9 @@ impl
                 .url(&types::TokenizationType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::TokenizationType::get_headers(self, req, connectors)?)
-                .body(types::TokenizationType::get_request_body(self, req)?)
+                .body(types::TokenizationType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -365,6 +372,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::SetupMandateRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = gocardless::GocardlessMandateRequest::try_from(req)?;
         let gocardless_req = types::RequestBody::log_and_get_request_body(
@@ -388,7 +396,9 @@ impl
                     .url(&types::SetupMandateType::get_url(self, req, connectors)?)
                     .attach_default_headers()
                     .headers(types::SetupMandateType::get_headers(self, req, connectors)?)
-                    .body(types::SetupMandateType::get_request_body(self, req)?)
+                    .body(types::SetupMandateType::get_request_body(
+                        self, req, connectors,
+                    )?)
                     .build(),
             ))
         } else {
@@ -446,6 +456,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = gocardless::GocardlessRouterData::try_from((
             &self.get_currency_unit(),
@@ -477,7 +488,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -611,6 +624,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = gocardless::GocardlessRouterData::try_from((
             &self.get_currency_unit(),
@@ -639,7 +653,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/helcim.rs b/crates/router/src/connector/helcim.rs
index 87fcfdd36d88..f7089bbd41b5 100644
--- a/crates/router/src/connector/helcim.rs
+++ b/crates/router/src/connector/helcim.rs
@@ -137,6 +137,7 @@ impl ConnectorCommon for Helcim {
             code: NO_ERROR_CODE.to_owned(),
             message: error_string.clone(),
             reason: Some(error_string),
+            attempt_status: None,
         })
     }
 }
@@ -192,6 +193,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::SetupMandateRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = helcim::HelcimVerifyRequest::try_from(req)?;
 
@@ -213,7 +215,9 @@ impl
                 .url(&types::SetupMandateType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::SetupMandateType::get_headers(self, req, connectors)?)
-                .body(types::SetupMandateType::get_request_body(self, req)?)
+                .body(types::SetupMandateType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -269,6 +273,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = helcim::HelcimRouterData::try_from((
             &self.get_currency_unit(),
@@ -300,7 +305,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -440,6 +447,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = helcim::HelcimRouterData::try_from((
             &self.get_currency_unit(),
@@ -469,7 +477,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -524,6 +534,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = helcim::HelcimVoidRequest::try_from(req)?;
         let helcim_req = types::RequestBody::log_and_get_request_body(
@@ -545,7 +556,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -599,6 +612,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = helcim::HelcimRouterData::try_from((
             &self.get_currency_unit(),
@@ -627,7 +641,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -705,7 +721,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/iatapay.rs b/crates/router/src/connector/iatapay.rs
index 3a813c50cf6b..008047c1d366 100644
--- a/crates/router/src/connector/iatapay.rs
+++ b/crates/router/src/connector/iatapay.rs
@@ -90,6 +90,10 @@ impl ConnectorCommon for Iatapay {
         "application/json"
     }
 
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Base
+    }
+
     fn base_url<'a>(&self, connectors: &'a settings::Connectors) -> &'a str {
         connectors.iatapay.base_url.as_ref()
     }
@@ -120,6 +124,7 @@ impl ConnectorCommon for Iatapay {
             code: response.error,
             message: response.message,
             reason: response.reason,
+            attempt_status: None,
         })
     }
 }
@@ -173,6 +178,7 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
     fn get_request_body(
         &self,
         req: &types::RefreshTokenRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = iatapay::IatapayAuthUpdateRequest::try_from(req)?;
         let iatapay_req = types::RequestBody::log_and_get_request_body(
@@ -194,7 +200,9 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
                 .attach_default_headers()
                 .headers(types::RefreshTokenType::get_headers(self, req, connectors)?)
                 .url(&types::RefreshTokenType::get_url(self, req, connectors)?)
-                .body(types::RefreshTokenType::get_request_body(self, req)?)
+                .body(types::RefreshTokenType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         );
 
@@ -231,6 +239,7 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
             code: response.error,
             message: response.path,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -270,8 +279,15 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let req_obj = iatapay::IatapayPaymentsRequest::try_from(req)?;
+        let connector_router_data = iatapay::IatapayRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+        let req_obj = iatapay::IatapayPaymentsRequest::try_from(&connector_router_data)?;
         let iatapay_req = types::RequestBody::log_and_get_request_body(
             &req_obj,
             Encode::<iatapay::IatapayPaymentsRequest>::encode_to_string_of_json,
@@ -295,7 +311,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -450,8 +468,15 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let req_obj = iatapay::IatapayRefundRequest::try_from(req)?;
+        let connector_router_data = iatapay::IatapayRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.payment_amount,
+            req,
+        ))?;
+        let req_obj = iatapay::IatapayRefundRequest::try_from(&connector_router_data)?;
         let iatapay_req = types::RequestBody::log_and_get_request_body(
             &req_obj,
             Encode::<iatapay::IatapayRefundRequest>::encode_to_string_of_json,
@@ -472,7 +497,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -542,7 +569,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/iatapay/transformers.rs b/crates/router/src/connector/iatapay/transformers.rs
index f98798fe5be4..7cdfafc858b6 100644
--- a/crates/router/src/connector/iatapay/transformers.rs
+++ b/crates/router/src/connector/iatapay/transformers.rs
@@ -8,7 +8,7 @@ use crate::{
     connector::utils::{self, PaymentsAuthorizeRequestData, RefundsRequestData, RouterData},
     core::errors,
     services,
-    types::{self, api, storage::enums},
+    types::{self, api, storage::enums, PaymentsAuthorizeData},
 };
 
 // Every access token will be valid for 5 minutes. It contains grant_type and scope for different type of access, but for our usecases it should be only 'client_credentials' and 'payment' resp(as per doc) for all type of api call.
@@ -26,7 +26,34 @@ impl TryFrom<&types::RefreshTokenRouterData> for IatapayAuthUpdateRequest {
         })
     }
 }
-
+#[derive(Debug, Serialize)]
+pub struct IatapayRouterData<T> {
+    amount: f64,
+    router_data: T,
+}
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for IatapayRouterData<T>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        (_currency_unit, _currency, _amount, item): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            amount: utils::to_currency_base_unit_asf64(_amount, _currency)?,
+            router_data: item,
+        })
+    }
+}
 #[derive(Debug, Deserialize)]
 pub struct IatapayAuthUpdateResponse {
     pub access_token: Secret<String>,
@@ -80,10 +107,29 @@ pub struct IatapayPaymentsRequest {
     payer_info: Option<PayerInfo>,
 }
 
-impl TryFrom<&types::PaymentsAuthorizeRouterData> for IatapayPaymentsRequest {
+impl
+    TryFrom<
+        &IatapayRouterData<
+            &types::RouterData<
+                types::api::payments::Authorize,
+                PaymentsAuthorizeData,
+                types::PaymentsResponseData,
+            >,
+        >,
+    > for IatapayPaymentsRequest
+{
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
-        let payment_method = item.payment_method;
+
+    fn try_from(
+        item: &IatapayRouterData<
+            &types::RouterData<
+                types::api::payments::Authorize,
+                PaymentsAuthorizeData,
+                types::PaymentsResponseData,
+            >,
+        >,
+    ) -> Result<Self, Self::Error> {
+        let payment_method = item.router_data.payment_method;
         let country = match payment_method {
             PaymentMethod::Upi => "IN".to_string(),
 
@@ -97,27 +143,26 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for IatapayPaymentsRequest {
             | PaymentMethod::BankDebit
             | PaymentMethod::Reward
             | PaymentMethod::Voucher
-            | PaymentMethod::GiftCard => item.get_billing_country()?.to_string(),
+            | PaymentMethod::GiftCard => item.router_data.get_billing_country()?.to_string(),
         };
-        let return_url = item.get_return_url()?;
-        let payer_info = match item.request.payment_method_data.clone() {
+        let return_url = item.router_data.get_return_url()?;
+        let payer_info = match item.router_data.request.payment_method_data.clone() {
             api::PaymentMethodData::Upi(upi_data) => upi_data.vpa_id.map(|id| PayerInfo {
                 token_id: id.switch_strategy(),
             }),
             _ => None,
         };
-        let amount =
-            utils::to_currency_base_unit_asf64(item.request.amount, item.request.currency)?;
         let payload = Self {
-            merchant_id: IatapayAuthType::try_from(&item.connector_auth_type)?.merchant_id,
-            merchant_payment_id: Some(item.payment_id.clone()),
-            amount,
-            currency: item.request.currency.to_string(),
+            merchant_id: IatapayAuthType::try_from(&item.router_data.connector_auth_type)?
+                .merchant_id,
+            merchant_payment_id: Some(item.router_data.connector_request_reference_id.clone()),
+            amount: item.amount,
+            currency: item.router_data.request.currency.to_string(),
             country: country.clone(),
             locale: format!("en-{}", country),
             redirect_urls: get_redirect_url(return_url),
             payer_info,
-            notification_url: item.request.get_webhook_url()?,
+            notification_url: item.router_data.request.get_webhook_url()?,
         };
         Ok(payload)
     }
@@ -275,18 +320,19 @@ pub struct IatapayRefundRequest {
     pub notification_url: String,
 }
 
-impl<F> TryFrom<&types::RefundsRouterData<F>> for IatapayRefundRequest {
+impl<F> TryFrom<&IatapayRouterData<&types::RefundsRouterData<F>>> for IatapayRefundRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
-        let amount =
-            utils::to_currency_base_unit_asf64(item.request.refund_amount, item.request.currency)?;
+    fn try_from(
+        item: &IatapayRouterData<&types::RefundsRouterData<F>>,
+    ) -> Result<Self, Self::Error> {
         Ok(Self {
-            amount,
-            merchant_id: IatapayAuthType::try_from(&item.connector_auth_type)?.merchant_id,
-            merchant_refund_id: Some(item.request.refund_id.clone()),
-            currency: item.request.currency.to_string(),
-            bank_transfer_description: item.request.reason.clone(),
-            notification_url: item.request.get_webhook_url()?,
+            amount: item.amount,
+            merchant_id: IatapayAuthType::try_from(&item.router_data.connector_auth_type)?
+                .merchant_id,
+            merchant_refund_id: Some(item.router_data.request.refund_id.clone()),
+            currency: item.router_data.request.currency.to_string(),
+            bank_transfer_description: item.router_data.request.reason.clone(),
+            notification_url: item.router_data.request.get_webhook_url()?,
         })
     }
 }
diff --git a/crates/router/src/connector/klarna.rs b/crates/router/src/connector/klarna.rs
index 1ab9c805a46e..3670f65a2f02 100644
--- a/crates/router/src/connector/klarna.rs
+++ b/crates/router/src/connector/klarna.rs
@@ -75,6 +75,7 @@ impl ConnectorCommon for Klarna {
             code: response.error_code,
             message: consts::NO_ERROR_MESSAGE.to_string(),
             reason,
+            attempt_status: None,
         })
     }
 }
@@ -153,6 +154,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsSessionRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = klarna::KlarnaSessionRequest::try_from(req)?;
         // encode only for for urlencoded things.
@@ -177,7 +179,9 @@ impl
                 .headers(types::PaymentsSessionType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsSessionType::get_request_body(self, req)?)
+                .body(types::PaymentsSessionType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -410,6 +414,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = klarna::KlarnaRouterData::try_from((
             &self.get_currency_unit(),
@@ -441,7 +446,9 @@ impl
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/klarna/transformers.rs b/crates/router/src/connector/klarna/transformers.rs
index 31e356d47651..563410ee99d0 100644
--- a/crates/router/src/connector/klarna/transformers.rs
+++ b/crates/router/src/connector/klarna/transformers.rs
@@ -159,12 +159,14 @@ impl TryFrom<types::PaymentsResponseRouterData<KlarnaPaymentsResponse>>
     ) -> Result<Self, Self::Error> {
         Ok(Self {
             response: Ok(types::PaymentsResponseData::TransactionResponse {
-                resource_id: types::ResponseId::ConnectorTransactionId(item.response.order_id),
+                resource_id: types::ResponseId::ConnectorTransactionId(
+                    item.response.order_id.clone(),
+                ),
                 redirection_data: None,
                 mandate_reference: None,
                 connector_metadata: None,
                 network_txn_id: None,
-                connector_response_reference_id: None,
+                connector_response_reference_id: Some(item.response.order_id.clone()),
             }),
             status: item.response.fraud_status.into(),
             ..item.data
diff --git a/crates/router/src/connector/mollie.rs b/crates/router/src/connector/mollie.rs
index 38abed9dea6a..ef3eb6a3e7b3 100644
--- a/crates/router/src/connector/mollie.rs
+++ b/crates/router/src/connector/mollie.rs
@@ -62,6 +62,10 @@ impl ConnectorCommon for Mollie {
         "mollie"
     }
 
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Base
+    }
+
     fn base_url<'a>(&self, connectors: &'a settings::Connectors) -> &'a str {
         connectors.mollie.base_url.as_ref()
     }
@@ -94,6 +98,7 @@ impl ConnectorCommon for Mollie {
                 .unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()),
             message: response.detail,
             reason: response.field,
+            attempt_status: None,
         })
     }
 }
@@ -145,6 +150,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::TokenizationRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = mollie::MollieCardTokenRequest::try_from(req)?;
         let mollie_req = types::RequestBody::log_and_get_request_body(
@@ -165,7 +171,9 @@ impl
                 .url(&types::TokenizationType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::TokenizationType::get_headers(self, req, connectors)?)
-                .body(types::TokenizationType::get_request_body(self, req)?)
+                .body(types::TokenizationType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -228,8 +236,15 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let req_obj = mollie::MolliePaymentsRequest::try_from(req)?;
+        let router_obj = mollie::MollieRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+        let req_obj = mollie::MolliePaymentsRequest::try_from(&router_obj)?;
         let mollie_req = types::RequestBody::log_and_get_request_body(
             &req_obj,
             utils::Encode::<mollie::MolliePaymentsRequest>::encode_to_string_of_json,
@@ -253,7 +268,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -416,8 +433,15 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let req_obj = mollie::MollieRefundRequest::try_from(req)?;
+        let router_obj = mollie::MollieRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.refund_amount,
+            req,
+        ))?;
+        let req_obj = mollie::MollieRefundRequest::try_from(&router_obj)?;
         let mollie_req = types::RequestBody::log_and_get_request_body(
             &req_obj,
             utils::Encode::<mollie::MollieRefundRequest>::encode_to_string_of_json,
@@ -438,7 +462,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/mollie/transformers.rs b/crates/router/src/connector/mollie/transformers.rs
index d0036d3c2f55..b77077ae709f 100644
--- a/crates/router/src/connector/mollie/transformers.rs
+++ b/crates/router/src/connector/mollie/transformers.rs
@@ -9,8 +9,8 @@ use url::Url;
 
 use crate::{
     connector::utils::{
-        self, AddressDetailsData, BrowserInformationData, CardData, PaymentsAuthorizeRequestData,
-        RouterData,
+        self, AddressDetailsData, BrowserInformationData, CardData,
+        PaymentMethodTokenizationRequestData, PaymentsAuthorizeRequestData, RouterData,
     },
     core::errors,
     services, types,
@@ -19,6 +19,38 @@ use crate::{
 
 type Error = error_stack::Report<errors::ConnectorError>;
 
+#[derive(Debug, Serialize)]
+pub struct MollieRouterData<T> {
+    pub amount: String,
+    pub router_data: T,
+}
+
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for MollieRouterData<T>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+
+    fn try_from(
+        (currency_unit, currency, amount, router_data): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        let amount = utils::get_amount_as_string(currency_unit, amount, currency)?;
+        Ok(Self {
+            amount,
+            router_data,
+        })
+    }
+}
+
 #[derive(Debug, Serialize)]
 #[serde(rename_all = "camelCase")]
 pub struct MolliePaymentsRequest {
@@ -30,7 +62,7 @@ pub struct MolliePaymentsRequest {
     locale: Option<String>,
     #[serde(flatten)]
     payment_method_data: PaymentMethodData,
-    metadata: Option<serde_json::Value>,
+    metadata: Option<MollieMetadata>,
     sequence_type: SequenceType,
     mandate_id: Option<String>,
 }
@@ -116,54 +148,61 @@ pub struct Address {
     pub country: api_models::enums::CountryAlpha2,
 }
 
-pub struct MollieBrowserInfo {
-    language: String,
+#[derive(Debug, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct MollieMetadata {
+    pub order_id: String,
 }
 
-impl TryFrom<&types::PaymentsAuthorizeRouterData> for MolliePaymentsRequest {
+impl TryFrom<&MollieRouterData<&types::PaymentsAuthorizeRouterData>> for MolliePaymentsRequest {
     type Error = Error;
-    fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
+    fn try_from(
+        item: &MollieRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
         let amount = Amount {
-            currency: item.request.currency,
-            value: utils::to_currency_base_unit(item.request.amount, item.request.currency)?,
+            currency: item.router_data.request.currency,
+            value: item.amount.clone(),
         };
-        let description = item.get_description()?;
-        let redirect_url = item.request.get_return_url()?;
-        let payment_method_data = match item.request.capture_method.unwrap_or_default() {
-            enums::CaptureMethod::Automatic => match &item.request.payment_method_data {
-                api_models::payments::PaymentMethodData::Card(_) => {
-                    let pm_token = item.get_payment_method_token()?;
-                    Ok(PaymentMethodData::CreditCard(Box::new(
-                        CreditCardMethodData {
-                            billing_address: get_billing_details(item)?,
-                            shipping_address: get_shipping_details(item)?,
-                            card_token: Some(Secret::new(match pm_token {
-                                types::PaymentMethodToken::Token(token) => token,
-                                types::PaymentMethodToken::ApplePayDecrypt(_) => {
-                                    Err(errors::ConnectorError::InvalidWalletToken)?
-                                }
-                            })),
-                        },
-                    )))
-                }
-                api_models::payments::PaymentMethodData::BankRedirect(ref redirect_data) => {
-                    PaymentMethodData::try_from(redirect_data)
-                }
-                api_models::payments::PaymentMethodData::Wallet(ref wallet_data) => {
-                    get_payment_method_for_wallet(item, wallet_data)
-                }
-                api_models::payments::PaymentMethodData::BankDebit(ref directdebit_data) => {
-                    PaymentMethodData::try_from(directdebit_data)
+        let description = item.router_data.get_description()?;
+        let redirect_url = item.router_data.request.get_return_url()?;
+        let payment_method_data = match item.router_data.request.capture_method.unwrap_or_default()
+        {
+            enums::CaptureMethod::Automatic => {
+                match &item.router_data.request.payment_method_data {
+                    api_models::payments::PaymentMethodData::Card(_) => {
+                        let pm_token = item.router_data.get_payment_method_token()?;
+                        Ok(PaymentMethodData::CreditCard(Box::new(
+                            CreditCardMethodData {
+                                billing_address: get_billing_details(item.router_data)?,
+                                shipping_address: get_shipping_details(item.router_data)?,
+                                card_token: Some(Secret::new(match pm_token {
+                                    types::PaymentMethodToken::Token(token) => token,
+                                    types::PaymentMethodToken::ApplePayDecrypt(_) => {
+                                        Err(errors::ConnectorError::InvalidWalletToken)?
+                                    }
+                                })),
+                            },
+                        )))
+                    }
+                    api_models::payments::PaymentMethodData::BankRedirect(ref redirect_data) => {
+                        PaymentMethodData::try_from(redirect_data)
+                    }
+                    api_models::payments::PaymentMethodData::Wallet(ref wallet_data) => {
+                        get_payment_method_for_wallet(item.router_data, wallet_data)
+                    }
+                    api_models::payments::PaymentMethodData::BankDebit(ref directdebit_data) => {
+                        PaymentMethodData::try_from(directdebit_data)
+                    }
+                    _ => Err(errors::ConnectorError::NotImplemented(
+                        "Payment Method".to_string(),
+                    ))
+                    .into_report(),
                 }
-                _ => Err(errors::ConnectorError::NotImplemented(
-                    "Payment Method".to_string(),
-                ))
-                .into_report(),
-            },
+            }
             _ => Err(errors::ConnectorError::FlowNotSupported {
                 flow: format!(
                     "{} capture",
-                    item.request.capture_method.unwrap_or_default()
+                    item.router_data.request.capture_method.unwrap_or_default()
                 ),
                 connector: "Mollie".to_string(),
             })
@@ -179,7 +218,9 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for MolliePaymentsRequest {
             webhook_url: "".to_string(),
             locale: None,
             payment_method_data,
-            metadata: None,
+            metadata: Some(MollieMetadata {
+                order_id: item.router_data.connector_request_reference_id.clone(),
+            }),
             sequence_type: SequenceType::Oneoff,
             mandate_id: None,
         })
@@ -250,12 +291,7 @@ impl TryFrom<&types::TokenizationRouterData> for MollieCardTokenRequest {
                 let card_expiry_date =
                     ccard.get_card_expiry_month_year_2_digit_with_delimiter("/".to_owned());
                 let card_cvv = ccard.card_cvc;
-                let browser_info = get_browser_info(item)?;
-                let locale = browser_info
-                    .ok_or(errors::ConnectorError::MissingRequiredField {
-                        field_name: "browser_info.language",
-                    })?
-                    .language;
+                let locale = item.request.get_browser_info()?.get_language()?;
                 let testmode =
                     item.test_mode
                         .ok_or(errors::ConnectorError::MissingRequiredField {
@@ -349,24 +385,6 @@ fn get_address_details(
     Ok(address_details)
 }
 
-fn get_browser_info(
-    item: &types::TokenizationRouterData,
-) -> Result<Option<MollieBrowserInfo>, error_stack::Report<errors::ConnectorError>> {
-    if matches!(item.auth_type, enums::AuthenticationType::ThreeDs) {
-        item.request
-            .browser_info
-            .as_ref()
-            .map(|info| {
-                Ok(MollieBrowserInfo {
-                    language: info.get_language()?,
-                })
-            })
-            .transpose()
-    } else {
-        Ok(None)
-    }
-}
-
 #[derive(Debug, Deserialize)]
 #[serde(rename_all = "camelCase")]
 pub struct MolliePaymentsResponse {
@@ -374,7 +392,7 @@ pub struct MolliePaymentsResponse {
     pub id: String,
     pub amount: Amount,
     pub description: Option<String>,
-    pub metadata: Option<serde_json::Value>,
+    pub metadata: Option<MollieMetadata>,
     pub status: MolliePaymentStatus,
     pub is_cancelable: Option<bool>,
     pub sequence_type: SequenceType,
@@ -507,12 +525,12 @@ impl<F, T>
         Ok(Self {
             status: enums::AttemptStatus::from(item.response.status),
             response: Ok(types::PaymentsResponseData::TransactionResponse {
-                resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
+                resource_id: types::ResponseId::ConnectorTransactionId(item.response.id.clone()),
                 redirection_data: url,
                 mandate_reference: None,
                 connector_metadata: None,
                 network_txn_id: None,
-                connector_response_reference_id: None,
+                connector_response_reference_id: Some(item.response.id),
             }),
             ..item.data
         })
@@ -524,18 +542,24 @@ impl<F, T>
 pub struct MollieRefundRequest {
     amount: Amount,
     description: Option<String>,
+    metadata: Option<MollieMetadata>,
 }
 
-impl<F> TryFrom<&types::RefundsRouterData<F>> for MollieRefundRequest {
+impl<F> TryFrom<&MollieRouterData<&types::RefundsRouterData<F>>> for MollieRefundRequest {
     type Error = Error;
-    fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
+    fn try_from(
+        item: &MollieRouterData<&types::RefundsRouterData<F>>,
+    ) -> Result<Self, Self::Error> {
         let amount = Amount {
-            currency: item.request.currency,
-            value: utils::to_currency_base_unit(item.request.refund_amount, item.request.currency)?,
+            currency: item.router_data.request.currency,
+            value: item.amount.clone(),
         };
         Ok(Self {
             amount,
-            description: item.request.reason.to_owned(),
+            description: item.router_data.request.reason.to_owned(),
+            metadata: Some(MollieMetadata {
+                order_id: item.router_data.request.refund_id.clone(),
+            }),
         })
     }
 }
@@ -550,7 +574,7 @@ pub struct RefundResponse {
     settlement_amount: Option<Amount>,
     status: MollieRefundStatus,
     description: Option<String>,
-    metadata: serde_json::Value,
+    metadata: Option<MollieMetadata>,
     payment_id: String,
     #[serde(rename = "_links")]
     links: Links,
@@ -603,6 +627,4 @@ pub struct ErrorResponse {
     pub title: Option<String>,
     pub detail: String,
     pub field: Option<String>,
-    #[serde(rename = "_links")]
-    pub links: Option<Links>,
 }
diff --git a/crates/router/src/connector/multisafepay.rs b/crates/router/src/connector/multisafepay.rs
index 120ea23d7ca6..9dc54e7b72e3 100644
--- a/crates/router/src/connector/multisafepay.rs
+++ b/crates/router/src/connector/multisafepay.rs
@@ -45,6 +45,10 @@ impl ConnectorCommon for Multisafepay {
         "multisafepay"
     }
 
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Minor
+    }
+
     fn common_get_content_type(&self) -> &'static str {
         "application/json"
     }
@@ -79,6 +83,7 @@ impl ConnectorCommon for Multisafepay {
             code: response.error_code.to_string(),
             message: response.error_info,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -196,10 +201,11 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
         data: &types::PaymentsSyncRouterData,
         res: Response,
     ) -> CustomResult<types::PaymentsSyncRouterData, errors::ConnectorError> {
-        let response: multisafepay::MultisafepayPaymentsResponse = res
+        let response: multisafepay::MultisafepayAuthResponse = res
             .response
             .parse_struct("multisafepay PaymentsResponse")
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+
         types::RouterData::try_from(types::ResponseRouterData {
             response,
             data: data.clone(),
@@ -256,8 +262,15 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let req_obj = multisafepay::MultisafepayPaymentsRequest::try_from(req)?;
+        let connector_router_data = multisafepay::MultisafepayRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+        let req_obj = multisafepay::MultisafepayPaymentsRequest::try_from(&connector_router_data)?;
         let multisafepay_req = types::RequestBody::log_and_get_request_body(
             &req_obj,
             utils::Encode::<multisafepay::MultisafepayPaymentsRequest>::encode_to_string_of_json,
@@ -281,7 +294,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -291,10 +306,11 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
         data: &types::PaymentsAuthorizeRouterData,
         res: Response,
     ) -> CustomResult<types::PaymentsAuthorizeRouterData, errors::ConnectorError> {
-        let response: multisafepay::MultisafepayPaymentsResponse = res
+        let response: multisafepay::MultisafepayAuthResponse = res
             .response
             .parse_struct("MultisafepayPaymentsResponse")
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+
         types::ResponseRouterData {
             response,
             data: data.clone(),
@@ -350,10 +366,18 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let connector_req = multisafepay::MultisafepayRefundRequest::try_from(req)?;
+        let connector_req = multisafepay::MultisafepayRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.refund_amount,
+            req,
+        ))?;
+        let req_obj = multisafepay::MultisafepayRefundRequest::try_from(&connector_req)?;
+
         let multisafepay_req = types::RequestBody::log_and_get_request_body(
-            &connector_req,
+            &req_obj,
             utils::Encode::<multisafepay::MultisafepayPaymentsRequest>::encode_to_string_of_json,
         )
         .change_context(errors::ConnectorError::RequestEncodingFailed)?;
@@ -372,7 +396,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -382,17 +408,17 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
         data: &types::RefundsRouterData<api::Execute>,
         res: Response,
     ) -> CustomResult<types::RefundsRouterData<api::Execute>, errors::ConnectorError> {
-        let response: multisafepay::RefundResponse = res
+        let response: multisafepay::MultisafepayRefundResponse = res
             .response
             .parse_struct("multisafepay RefundResponse")
-            .change_context(errors::ConnectorError::RequestEncodingFailed)?;
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
         types::ResponseRouterData {
             response,
             data: data.clone(),
             http_code: res.status_code,
         }
         .try_into()
-        .change_context(errors::ConnectorError::ResponseHandlingFailed)
+        .change_context(errors::ConnectorError::ResponseDeserializationFailed)
     }
 
     fn get_error_response(
@@ -445,7 +471,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -455,7 +483,7 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
         data: &types::RefundSyncRouterData,
         res: Response,
     ) -> CustomResult<types::RefundSyncRouterData, errors::ConnectorError> {
-        let response: multisafepay::RefundResponse = res
+        let response: multisafepay::MultisafepayRefundResponse = res
             .response
             .parse_struct("multisafepay RefundResponse")
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
@@ -465,7 +493,7 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
             http_code: res.status_code,
         }
         .try_into()
-        .change_context(errors::ConnectorError::ResponseHandlingFailed)
+        .change_context(errors::ConnectorError::ResponseDeserializationFailed)
     }
 
     fn get_error_response(
diff --git a/crates/router/src/connector/multisafepay/transformers.rs b/crates/router/src/connector/multisafepay/transformers.rs
index 385c85e0aa61..6e371b1e1a2b 100644
--- a/crates/router/src/connector/multisafepay/transformers.rs
+++ b/crates/router/src/connector/multisafepay/transformers.rs
@@ -13,6 +13,37 @@ use crate::{
     types::{self, api, storage::enums},
 };
 
+#[derive(Debug, Serialize)]
+pub struct MultisafepayRouterData<T> {
+    amount: i64,
+    router_data: T,
+}
+
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for MultisafepayRouterData<T>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+
+    fn try_from(
+        (_currency_unit, _currency, amount, item): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            amount,
+            router_data: item,
+        })
+    }
+}
+
 #[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
 #[serde(rename_all = "lowercase")]
 pub enum Type {
@@ -240,10 +271,14 @@ impl TryFrom<utils::CardIssuer> for Gateway {
     }
 }
 
-impl TryFrom<&types::PaymentsAuthorizeRouterData> for MultisafepayPaymentsRequest {
+impl TryFrom<&MultisafepayRouterData<&types::PaymentsAuthorizeRouterData>>
+    for MultisafepayPaymentsRequest
+{
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
-        let payment_type = match item.request.payment_method_data {
+    fn try_from(
+        item: &MultisafepayRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
+        let payment_type = match item.router_data.request.payment_method_data {
             api::PaymentMethodData::Card(ref _ccard) => Type::Direct,
             api::PaymentMethodData::MandatePayment => Type::Direct,
             api::PaymentMethodData::Wallet(ref wallet_data) => match wallet_data {
@@ -280,7 +315,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for MultisafepayPaymentsReques
             _ => Type::Redirect,
         };
 
-        let gateway = match item.request.payment_method_data {
+        let gateway = match item.router_data.request.payment_method_data {
             api::PaymentMethodData::Card(ref ccard) => {
                 Some(Gateway::try_from(ccard.get_card_issuer()?)?)
             }
@@ -334,11 +369,11 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for MultisafepayPaymentsReques
                 utils::get_unimplemented_payment_method_error_message("multisafepay"),
             ))?,
         };
-        let description = item.get_description()?;
+        let description = item.router_data.get_description()?;
         let payment_options = PaymentOptions {
             notification_url: None,
-            redirect_url: item.request.get_router_return_url()?,
-            cancel_url: item.request.get_router_return_url()?,
+            redirect_url: item.router_data.request.get_router_return_url()?,
+            cancel_url: item.router_data.request.get_router_return_url()?,
             close_window: None,
             notification_method: None,
             settings: None,
@@ -363,13 +398,14 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for MultisafepayPaymentsReques
             state: None,
             country: None,
             phone: None,
-            email: item.request.email.clone(),
+            email: item.router_data.request.email.clone(),
             user_agent: None,
             referrer: None,
-            reference: Some(item.connector_request_reference_id.clone()),
+            reference: Some(item.router_data.connector_request_reference_id.clone()),
         };
 
         let billing_address = item
+            .router_data
             .get_billing()?
             .address
             .as_ref()
@@ -384,7 +420,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for MultisafepayPaymentsReques
             country: billing_address.get_country()?.to_owned(),
         };
 
-        let gateway_info = match item.request.payment_method_data {
+        let gateway_info = match item.router_data.request.payment_method_data {
             api::PaymentMethodData::Card(ref ccard) => Some(GatewayInfo::Card(CardInfo {
                 card_number: Some(ccard.card_number.clone()),
                 card_expiry_date: Some(
@@ -481,9 +517,9 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for MultisafepayPaymentsReques
         Ok(Self {
             payment_type,
             gateway,
-            order_id: item.connector_request_reference_id.to_string(),
-            currency: item.request.currency.to_string(),
-            amount: item.request.amount,
+            order_id: item.router_data.connector_request_reference_id.to_string(),
+            currency: item.router_data.request.currency.to_string(),
+            amount: item.amount,
             description,
             payment_options: Some(payment_options),
             customer: Some(customer),
@@ -493,12 +529,13 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for MultisafepayPaymentsReques
             shopping_cart: None,
             capture: None,
             items: None,
-            recurring_model: if item.request.is_mandate_payment() {
+            recurring_model: if item.router_data.request.is_mandate_payment() {
                 Some(MandateType::Unscheduled)
             } else {
                 None
             },
             recurring_id: item
+                .router_data
                 .request
                 .mandate_id
                 .clone()
@@ -599,57 +636,77 @@ pub struct MultisafepayPaymentsResponse {
     pub data: Data,
 }
 
+#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
+#[serde(untagged)]
+pub enum MultisafepayAuthResponse {
+    ErrorResponse(MultisafepayErrorResponse),
+    PaymentResponse(MultisafepayPaymentsResponse),
+}
+
 impl<F, T>
-    TryFrom<
-        types::ResponseRouterData<F, MultisafepayPaymentsResponse, T, types::PaymentsResponseData>,
-    > for types::RouterData<F, T, types::PaymentsResponseData>
+    TryFrom<types::ResponseRouterData<F, MultisafepayAuthResponse, T, types::PaymentsResponseData>>
+    for types::RouterData<F, T, types::PaymentsResponseData>
 {
     type Error = error_stack::Report<errors::ParsingError>;
     fn try_from(
         item: types::ResponseRouterData<
             F,
-            MultisafepayPaymentsResponse,
+            MultisafepayAuthResponse,
             T,
             types::PaymentsResponseData,
         >,
     ) -> Result<Self, Self::Error> {
-        let redirection_data = item
-            .response
-            .data
-            .payment_url
-            .clone()
-            .map(|url| services::RedirectForm::from((url, services::Method::Get)));
-
-        let default_status = if item.response.success {
-            MultisafepayPaymentStatus::Initialized
-        } else {
-            MultisafepayPaymentStatus::Declined
-        };
-
-        let status = item.response.data.status.unwrap_or(default_status);
-
-        Ok(Self {
-            status: enums::AttemptStatus::from(status),
-            response: Ok(types::PaymentsResponseData::TransactionResponse {
-                resource_id: types::ResponseId::ConnectorTransactionId(
-                    item.response.data.order_id.clone(),
-                ),
-                redirection_data,
-                mandate_reference: item
-                    .response
+        match item.response {
+            MultisafepayAuthResponse::PaymentResponse(payment_response) => {
+                let redirection_data = payment_response
                     .data
-                    .payment_details
-                    .and_then(|payment_details| payment_details.recurring_id)
-                    .map(|id| types::MandateReference {
-                        connector_mandate_id: Some(id),
-                        payment_method_id: None,
+                    .payment_url
+                    .clone()
+                    .map(|url| services::RedirectForm::from((url, services::Method::Get)));
+
+                let default_status = if payment_response.success {
+                    MultisafepayPaymentStatus::Initialized
+                } else {
+                    MultisafepayPaymentStatus::Declined
+                };
+
+                let status = payment_response.data.status.unwrap_or(default_status);
+
+                Ok(Self {
+                    status: enums::AttemptStatus::from(status),
+                    response: Ok(types::PaymentsResponseData::TransactionResponse {
+                        resource_id: types::ResponseId::ConnectorTransactionId(
+                            payment_response.data.order_id.clone(),
+                        ),
+                        redirection_data,
+                        mandate_reference: payment_response
+                            .data
+                            .payment_details
+                            .and_then(|payment_details| payment_details.recurring_id)
+                            .map(|id| types::MandateReference {
+                                connector_mandate_id: Some(id),
+                                payment_method_id: None,
+                            }),
+                        connector_metadata: None,
+                        network_txn_id: None,
+                        connector_response_reference_id: Some(
+                            payment_response.data.order_id.clone(),
+                        ),
                     }),
-                connector_metadata: None,
-                network_txn_id: None,
-                connector_response_reference_id: Some(item.response.data.order_id.clone()),
+                    ..item.data
+                })
+            }
+            MultisafepayAuthResponse::ErrorResponse(error_response) => Ok(Self {
+                response: Err(types::ErrorResponse {
+                    code: error_response.error_code.to_string(),
+                    message: error_response.error_info.clone(),
+                    reason: Some(error_response.error_info),
+                    status_code: item.http_code,
+                    attempt_status: None,
+                }),
+                ..item.data
             }),
-            ..item.data
-        })
+        }
     }
 }
 
@@ -664,14 +721,18 @@ pub struct MultisafepayRefundRequest {
     pub checkout_data: Option<ShoppingCart>,
 }
 
-impl<F> TryFrom<&types::RefundsRouterData<F>> for MultisafepayRefundRequest {
+impl<F> TryFrom<&MultisafepayRouterData<&types::RefundsRouterData<F>>>
+    for MultisafepayRefundRequest
+{
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
+    fn try_from(
+        item: &MultisafepayRouterData<&types::RefundsRouterData<F>>,
+    ) -> Result<Self, Self::Error> {
         Ok(Self {
-            currency: item.request.currency,
-            amount: item.request.refund_amount,
-            description: item.description.clone(),
-            refund_order_id: Some(item.request.refund_id.clone()),
+            currency: item.router_data.request.currency,
+            amount: item.amount,
+            description: item.router_data.description.clone(),
+            refund_order_id: Some(item.router_data.request.refund_id.clone()),
             checkout_data: None,
         })
     }
@@ -706,61 +767,95 @@ pub struct RefundData {
     pub error_code: Option<i32>,
     pub error_info: Option<String>,
 }
-#[derive(Default, Debug, Clone, Serialize, Deserialize)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
 pub struct RefundResponse {
     pub success: bool,
     pub data: RefundData,
 }
 
-impl TryFrom<types::RefundsResponseRouterData<api::Execute, RefundResponse>>
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(untagged)]
+pub enum MultisafepayRefundResponse {
+    ErrorResponse(MultisafepayErrorResponse),
+    RefundResponse(RefundResponse),
+}
+
+impl TryFrom<types::RefundsResponseRouterData<api::Execute, MultisafepayRefundResponse>>
     for types::RefundsRouterData<api::Execute>
 {
     type Error = error_stack::Report<errors::ParsingError>;
     fn try_from(
-        item: types::RefundsResponseRouterData<api::Execute, RefundResponse>,
+        item: types::RefundsResponseRouterData<api::Execute, MultisafepayRefundResponse>,
     ) -> Result<Self, Self::Error> {
-        let refund_stat = if item.response.success {
-            RefundStatus::Succeeded
-        } else {
-            RefundStatus::Failed
-        };
-
-        Ok(Self {
-            response: Ok(types::RefundsResponseData {
-                connector_refund_id: item.response.data.refund_id.to_string(),
-                refund_status: enums::RefundStatus::from(refund_stat),
+        match item.response {
+            MultisafepayRefundResponse::RefundResponse(refund_data) => {
+                let refund_status = if refund_data.success {
+                    RefundStatus::Succeeded
+                } else {
+                    RefundStatus::Failed
+                };
+
+                Ok(Self {
+                    response: Ok(types::RefundsResponseData {
+                        connector_refund_id: refund_data.data.refund_id.to_string(),
+                        refund_status: enums::RefundStatus::from(refund_status),
+                    }),
+                    ..item.data
+                })
+            }
+            MultisafepayRefundResponse::ErrorResponse(error_response) => Ok(Self {
+                response: Err(types::ErrorResponse {
+                    code: error_response.error_code.to_string(),
+                    message: error_response.error_info.clone(),
+                    reason: Some(error_response.error_info),
+                    status_code: item.http_code,
+                    attempt_status: None,
+                }),
+                ..item.data
             }),
-            ..item.data
-        })
+        }
     }
 }
 
-impl TryFrom<types::RefundsResponseRouterData<api::RSync, RefundResponse>>
+impl TryFrom<types::RefundsResponseRouterData<api::RSync, MultisafepayRefundResponse>>
     for types::RefundsRouterData<api::RSync>
 {
     type Error = error_stack::Report<errors::ParsingError>;
     fn try_from(
-        item: types::RefundsResponseRouterData<api::RSync, RefundResponse>,
+        item: types::RefundsResponseRouterData<api::RSync, MultisafepayRefundResponse>,
     ) -> Result<Self, Self::Error> {
-        let refund_status = if item.response.success {
-            RefundStatus::Succeeded
-        } else {
-            RefundStatus::Failed
-        };
-
-        Ok(Self {
-            response: Ok(types::RefundsResponseData {
-                connector_refund_id: item.response.data.refund_id.to_string(),
-                refund_status: enums::RefundStatus::from(refund_status),
+        match item.response {
+            MultisafepayRefundResponse::RefundResponse(refund_data) => {
+                let refund_status = if refund_data.success {
+                    RefundStatus::Succeeded
+                } else {
+                    RefundStatus::Failed
+                };
+
+                Ok(Self {
+                    response: Ok(types::RefundsResponseData {
+                        connector_refund_id: refund_data.data.refund_id.to_string(),
+                        refund_status: enums::RefundStatus::from(refund_status),
+                    }),
+                    ..item.data
+                })
+            }
+            MultisafepayRefundResponse::ErrorResponse(error_response) => Ok(Self {
+                response: Err(types::ErrorResponse {
+                    code: error_response.error_code.to_string(),
+                    message: error_response.error_info.clone(),
+                    reason: Some(error_response.error_info),
+                    status_code: item.http_code,
+                    attempt_status: None,
+                }),
+                ..item.data
             }),
-            ..item.data
-        })
+        }
     }
 }
 
-#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
+#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone)]
 pub struct MultisafepayErrorResponse {
-    pub success: bool,
     pub error_code: i32,
     pub error_info: String,
 }
diff --git a/crates/router/src/connector/nexinets.rs b/crates/router/src/connector/nexinets.rs
index 30ae4ab25e50..f2e57792f284 100644
--- a/crates/router/src/connector/nexinets.rs
+++ b/crates/router/src/connector/nexinets.rs
@@ -130,6 +130,7 @@ impl ConnectorCommon for Nexinets {
             code: response.code.to_string(),
             message: static_message,
             reason: Some(connector_reason),
+            attempt_status: None,
         })
     }
 }
@@ -199,6 +200,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = nexinets::NexinetsPaymentsRequest::try_from(req)?;
         let nexinets_req = types::RequestBody::log_and_get_request_body(
@@ -224,7 +226,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -361,6 +365,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = nexinets::NexinetsCaptureOrVoidRequest::try_from(req)?;
         let nexinets_req = types::RequestBody::log_and_get_request_body(
@@ -384,7 +389,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -446,6 +453,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = nexinets::NexinetsCaptureOrVoidRequest::try_from(req)?;
         let nexinets_req = types::RequestBody::log_and_get_request_body(
@@ -465,7 +473,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
             .method(services::Method::Post)
             .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
             .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-            .body(types::PaymentsVoidType::get_request_body(self, req)?)
+            .body(types::PaymentsVoidType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
 
         Ok(Some(request))
@@ -528,6 +538,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = nexinets::NexinetsRefundRequest::try_from(req)?;
         let nexinets_req = types::RequestBody::log_and_get_request_body(
@@ -550,7 +561,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/nexinets/transformers.rs b/crates/router/src/connector/nexinets/transformers.rs
index 897d8f639d35..2af3ee0a1bb8 100644
--- a/crates/router/src/connector/nexinets/transformers.rs
+++ b/crates/router/src/connector/nexinets/transformers.rs
@@ -9,7 +9,7 @@ use url::Url;
 
 use crate::{
     connector::utils::{
-        CardData, PaymentsAuthorizeRequestData, PaymentsCancelRequestData, WalletData,
+        self, CardData, PaymentsAuthorizeRequestData, PaymentsCancelRequestData, WalletData,
     },
     consts,
     core::errors,
@@ -597,12 +597,35 @@ fn get_payment_details_and_product(
             api_models::payments::BankRedirectData::Sofort { .. } => {
                 Ok((None, NexinetsProduct::Sofort))
             }
-            _ => Err(errors::ConnectorError::NotImplemented(
-                "Payment methods".to_string(),
-            ))?,
+            api_models::payments::BankRedirectData::BancontactCard { .. }
+            | api_models::payments::BankRedirectData::Blik { .. }
+            | api_models::payments::BankRedirectData::Bizum { .. }
+            | api_models::payments::BankRedirectData::Interac { .. }
+            | api_models::payments::BankRedirectData::OnlineBankingCzechRepublic { .. }
+            | api_models::payments::BankRedirectData::OnlineBankingFinland { .. }
+            | api_models::payments::BankRedirectData::OnlineBankingPoland { .. }
+            | api_models::payments::BankRedirectData::OnlineBankingSlovakia { .. }
+            | api_models::payments::BankRedirectData::OpenBankingUk { .. }
+            | api_models::payments::BankRedirectData::Przelewy24 { .. }
+            | api_models::payments::BankRedirectData::Trustly { .. }
+            | api_models::payments::BankRedirectData::OnlineBankingFpx { .. }
+            | api_models::payments::BankRedirectData::OnlineBankingThailand { .. } => {
+                Err(errors::ConnectorError::NotImplemented(
+                    utils::get_unimplemented_payment_method_error_message("nexinets"),
+                ))?
+            }
         },
-        _ => Err(errors::ConnectorError::NotImplemented(
-            "Payment methods".to_string(),
+        PaymentMethodData::CardRedirect(_)
+        | PaymentMethodData::PayLater(_)
+        | PaymentMethodData::BankDebit(_)
+        | PaymentMethodData::BankTransfer(_)
+        | PaymentMethodData::Crypto(_)
+        | PaymentMethodData::MandatePayment
+        | PaymentMethodData::Reward
+        | PaymentMethodData::Upi(_)
+        | PaymentMethodData::Voucher(_)
+        | PaymentMethodData::GiftCard(_) => Err(errors::ConnectorError::NotImplemented(
+            utils::get_unimplemented_payment_method_error_message("nexinets"),
         ))?,
     }
 }
@@ -677,9 +700,34 @@ fn get_wallet_details(
             ))),
             NexinetsProduct::Applepay,
         )),
-        _ => Err(errors::ConnectorError::NotImplemented(
-            "Payment methods".to_string(),
-        ))?,
+        api_models::payments::WalletData::AliPayQr(_)
+        | api_models::payments::WalletData::AliPayRedirect(_)
+        | api_models::payments::WalletData::AliPayHkRedirect(_)
+        | api_models::payments::WalletData::MomoRedirect(_)
+        | api_models::payments::WalletData::KakaoPayRedirect(_)
+        | api_models::payments::WalletData::GoPayRedirect(_)
+        | api_models::payments::WalletData::GcashRedirect(_)
+        | api_models::payments::WalletData::ApplePayRedirect(_)
+        | api_models::payments::WalletData::ApplePayThirdPartySdk(_)
+        | api_models::payments::WalletData::DanaRedirect { .. }
+        | api_models::payments::WalletData::GooglePay(_)
+        | api_models::payments::WalletData::GooglePayRedirect(_)
+        | api_models::payments::WalletData::GooglePayThirdPartySdk(_)
+        | api_models::payments::WalletData::MbWayRedirect(_)
+        | api_models::payments::WalletData::MobilePayRedirect(_)
+        | api_models::payments::WalletData::PaypalSdk(_)
+        | api_models::payments::WalletData::SamsungPay(_)
+        | api_models::payments::WalletData::TwintRedirect { .. }
+        | api_models::payments::WalletData::VippsRedirect { .. }
+        | api_models::payments::WalletData::TouchNGoRedirect(_)
+        | api_models::payments::WalletData::WeChatPayRedirect(_)
+        | api_models::payments::WalletData::WeChatPayQr(_)
+        | api_models::payments::WalletData::CashappQr(_)
+        | api_models::payments::WalletData::SwishQr(_) => {
+            Err(errors::ConnectorError::NotImplemented(
+                utils::get_unimplemented_payment_method_error_message("nexinets"),
+            ))?
+        }
     }
 }
 
diff --git a/crates/router/src/connector/nmi.rs b/crates/router/src/connector/nmi.rs
index cdeb9c99d5ea..d7e9cd78bb88 100644
--- a/crates/router/src/connector/nmi.rs
+++ b/crates/router/src/connector/nmi.rs
@@ -58,6 +58,10 @@ impl ConnectorCommon for Nmi {
         "nmi"
     }
 
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Base
+    }
+
     fn base_url<'a>(&self, connectors: &'a settings::Connectors) -> &'a str {
         connectors.nmi.base_url.as_ref()
     }
@@ -139,6 +143,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::SetupMandateRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = nmi::NmiPaymentsRequest::try_from(req)?;
         let nmi_req = types::RequestBody::log_and_get_request_body(
@@ -159,7 +164,9 @@ impl
                 .method(services::Method::Post)
                 .url(&types::SetupMandateType::get_url(self, req, connectors)?)
                 .headers(types::SetupMandateType::get_headers(self, req, connectors)?)
-                .body(types::SetupMandateType::get_request_body(self, req)?)
+                .body(types::SetupMandateType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -209,8 +216,15 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let connector_req = nmi::NmiPaymentsRequest::try_from(req)?;
+        let connector_router_data = nmi::NmiRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+        let connector_req = nmi::NmiPaymentsRequest::try_from(&connector_router_data)?;
         let nmi_req = types::RequestBody::log_and_get_request_body(
             &connector_req,
             utils::Encode::<nmi::NmiPaymentsRequest>::url_encode,
@@ -233,7 +247,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -283,6 +299,7 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
     fn get_request_body(
         &self,
         req: &types::PaymentsSyncRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = nmi::NmiSyncRequest::try_from(req)?;
         let nmi_req = types::RequestBody::log_and_get_request_body(
@@ -303,7 +320,9 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
                 .method(services::Method::Post)
                 .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                 .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsSyncType::get_request_body(self, req)?)
+                .body(types::PaymentsSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -350,8 +369,15 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let connector_req = nmi::NmiCaptureRequest::try_from(req)?;
+        let connector_router_data = nmi::NmiRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount_to_capture,
+            req,
+        ))?;
+        let connector_req = nmi::NmiCaptureRequest::try_from(&connector_router_data)?;
         let nmi_req = types::RequestBody::log_and_get_request_body(
             &connector_req,
             utils::Encode::<NmiCaptureRequest>::url_encode,
@@ -372,7 +398,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -422,6 +450,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = nmi::NmiCancelRequest::try_from(req)?;
         let nmi_req = types::RequestBody::log_and_get_request_body(
@@ -442,7 +471,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .method(services::Method::Post)
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -490,8 +521,15 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let connector_req = nmi::NmiRefundRequest::try_from(req)?;
+        let connector_router_data = nmi::NmiRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.refund_amount,
+            req,
+        ))?;
+        let connector_req = nmi::NmiRefundRequest::try_from(&connector_router_data)?;
         let nmi_req = types::RequestBody::log_and_get_request_body(
             &connector_req,
             utils::Encode::<nmi::NmiRefundRequest>::url_encode,
@@ -512,7 +550,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
                 .headers(types::RefundExecuteType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::RefundExecuteType::get_request_body(self, req)?)
+                .body(types::RefundExecuteType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -560,6 +600,7 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::RSync>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = nmi::NmiSyncRequest::try_from(req)?;
         let nmi_req = types::RequestBody::log_and_get_request_body(
@@ -580,7 +621,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .method(services::Method::Post)
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/nmi/transformers.rs b/crates/router/src/connector/nmi/transformers.rs
index 3f64ff9eaca2..6e887f58858f 100644
--- a/crates/router/src/connector/nmi/transformers.rs
+++ b/crates/router/src/connector/nmi/transformers.rs
@@ -40,6 +40,37 @@ impl TryFrom<&ConnectorAuthType> for NmiAuthType {
     }
 }
 
+#[derive(Debug, Serialize)]
+pub struct NmiRouterData<T> {
+    pub amount: f64,
+    pub router_data: T,
+}
+
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for NmiRouterData<T>
+{
+    type Error = Report<errors::ConnectorError>;
+
+    fn try_from(
+        (_currency_unit, currency, amount, router_data): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            amount: utils::to_currency_base_unit_asf64(amount, currency)?,
+            router_data,
+        })
+    }
+}
+
 #[derive(Debug, Serialize)]
 pub struct NmiPaymentsRequest {
     #[serde(rename = "type")]
@@ -49,6 +80,7 @@ pub struct NmiPaymentsRequest {
     currency: enums::Currency,
     #[serde(flatten)]
     payment_method: PaymentMethod,
+    orderid: String,
 }
 
 #[derive(Debug, Serialize)]
@@ -76,24 +108,27 @@ pub struct ApplePayData {
     applepay_payment_data: Secret<String>,
 }
 
-impl TryFrom<&types::PaymentsAuthorizeRouterData> for NmiPaymentsRequest {
+impl TryFrom<&NmiRouterData<&types::PaymentsAuthorizeRouterData>> for NmiPaymentsRequest {
     type Error = Error;
-    fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
-        let transaction_type = match item.request.is_auto_capture()? {
+    fn try_from(
+        item: &NmiRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
+        let transaction_type = match item.router_data.request.is_auto_capture()? {
             true => TransactionType::Sale,
             false => TransactionType::Auth,
         };
-        let auth_type: NmiAuthType = (&item.connector_auth_type).try_into()?;
-        let amount =
-            utils::to_currency_base_unit_asf64(item.request.amount, item.request.currency)?;
-        let payment_method = PaymentMethod::try_from(&item.request.payment_method_data)?;
+        let auth_type: NmiAuthType = (&item.router_data.connector_auth_type).try_into()?;
+        let amount = item.amount;
+        let payment_method =
+            PaymentMethod::try_from(&item.router_data.request.payment_method_data)?;
 
         Ok(Self {
             transaction_type,
             security_key: auth_type.api_key,
             amount,
-            currency: item.request.currency,
+            currency: item.router_data.request.currency,
             payment_method,
+            orderid: item.router_data.connector_request_reference_id.clone(),
         })
     }
 }
@@ -206,6 +241,7 @@ impl TryFrom<&types::SetupMandateRouterData> for NmiPaymentsRequest {
             amount: 0.0,
             currency: item.request.currency,
             payment_method,
+            orderid: item.connector_request_reference_id.clone(),
         })
     }
 }
@@ -240,18 +276,17 @@ pub struct NmiCaptureRequest {
     pub amount: Option<f64>,
 }
 
-impl TryFrom<&types::PaymentsCaptureRouterData> for NmiCaptureRequest {
+impl TryFrom<&NmiRouterData<&types::PaymentsCaptureRouterData>> for NmiCaptureRequest {
     type Error = Error;
-    fn try_from(item: &types::PaymentsCaptureRouterData) -> Result<Self, Self::Error> {
-        let auth = NmiAuthType::try_from(&item.connector_auth_type)?;
+    fn try_from(
+        item: &NmiRouterData<&types::PaymentsCaptureRouterData>,
+    ) -> Result<Self, Self::Error> {
+        let auth = NmiAuthType::try_from(&item.router_data.connector_auth_type)?;
         Ok(Self {
             transaction_type: TransactionType::Capture,
             security_key: auth.api_key,
-            transactionid: item.request.connector_transaction_id.clone(),
-            amount: Some(utils::to_currency_base_unit_asf64(
-                item.request.amount_to_capture,
-                item.request.currency,
-            )?),
+            transactionid: item.router_data.request.connector_transaction_id.clone(),
+            amount: Some(item.amount),
         })
     }
 }
@@ -405,6 +440,7 @@ impl ForeignFrom<(StandardResponse, u16)> for types::ErrorResponse {
             message: response.responsetext,
             reason: None,
             status_code: http_code,
+            attempt_status: None,
         }
     }
 }
@@ -574,18 +610,15 @@ pub struct NmiRefundRequest {
     amount: f64,
 }
 
-impl<F> TryFrom<&types::RefundsRouterData<F>> for NmiRefundRequest {
+impl<F> TryFrom<&NmiRouterData<&types::RefundsRouterData<F>>> for NmiRefundRequest {
     type Error = Error;
-    fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
-        let auth_type: NmiAuthType = (&item.connector_auth_type).try_into()?;
+    fn try_from(item: &NmiRouterData<&types::RefundsRouterData<F>>) -> Result<Self, Self::Error> {
+        let auth_type: NmiAuthType = (&item.router_data.connector_auth_type).try_into()?;
         Ok(Self {
             transaction_type: TransactionType::Refund,
             security_key: auth_type.api_key,
-            transactionid: item.request.connector_transaction_id.clone(),
-            amount: utils::to_currency_base_unit_asf64(
-                item.request.refund_amount,
-                item.request.currency,
-            )?,
+            transactionid: item.router_data.request.connector_transaction_id.clone(),
+            amount: item.amount,
         })
     }
 }
diff --git a/crates/router/src/connector/noon.rs b/crates/router/src/connector/noon.rs
index 156e10928d3e..0ea73efd94bd 100644
--- a/crates/router/src/connector/noon.rs
+++ b/crates/router/src/connector/noon.rs
@@ -136,6 +136,7 @@ impl ConnectorCommon for Noon {
             code: response.result_code.to_string(),
             message: response.class_description,
             reason: Some(response.message),
+            attempt_status: None,
         })
     }
 }
@@ -153,6 +154,14 @@ impl ConnectorValidation for Noon {
             ),
         }
     }
+
+    fn validate_psync_reference_id(
+        &self,
+        _data: &types::PaymentsSyncRouterData,
+    ) -> CustomResult<(), errors::ConnectorError> {
+        // since we can make psync call with our reference_id, having connector_transaction_id is not an mandatory criteria
+        Ok(())
+    }
 }
 
 impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::PaymentsResponseData>
@@ -201,6 +210,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = noon::NoonPaymentsRequest::try_from(req)?;
         let noon_req = types::RequestBody::log_and_get_request_body(
@@ -226,7 +236,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -347,6 +359,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = noon::NoonPaymentsActionRequest::try_from(req)?;
         let noon_req = types::RequestBody::log_and_get_request_body(
@@ -370,7 +383,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -424,6 +439,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = noon::NoonPaymentsCancelRequest::try_from(req)?;
         let noon_req = types::RequestBody::log_and_get_request_body(
@@ -445,7 +461,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -498,6 +516,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = noon::NoonPaymentsActionRequest::try_from(req)?;
         let noon_req = types::RequestBody::log_and_get_request_body(
@@ -520,7 +539,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -585,7 +606,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/noon/transformers.rs b/crates/router/src/connector/noon/transformers.rs
index cde6de2e43b6..27a874930bcc 100644
--- a/crates/router/src/connector/noon/transformers.rs
+++ b/crates/router/src/connector/noon/transformers.rs
@@ -245,13 +245,51 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for NoonPaymentsRequest {
                                 return_url: item.request.get_router_return_url()?,
                             }))
                         }
-                        _ => Err(errors::ConnectorError::NotImplemented(
-                            "Wallets".to_string(),
-                        )),
+                        api_models::payments::WalletData::AliPayQr(_)
+                        | api_models::payments::WalletData::AliPayRedirect(_)
+                        | api_models::payments::WalletData::AliPayHkRedirect(_)
+                        | api_models::payments::WalletData::MomoRedirect(_)
+                        | api_models::payments::WalletData::KakaoPayRedirect(_)
+                        | api_models::payments::WalletData::GoPayRedirect(_)
+                        | api_models::payments::WalletData::GcashRedirect(_)
+                        | api_models::payments::WalletData::ApplePayRedirect(_)
+                        | api_models::payments::WalletData::ApplePayThirdPartySdk(_)
+                        | api_models::payments::WalletData::DanaRedirect {}
+                        | api_models::payments::WalletData::GooglePayRedirect(_)
+                        | api_models::payments::WalletData::GooglePayThirdPartySdk(_)
+                        | api_models::payments::WalletData::MbWayRedirect(_)
+                        | api_models::payments::WalletData::MobilePayRedirect(_)
+                        | api_models::payments::WalletData::PaypalSdk(_)
+                        | api_models::payments::WalletData::SamsungPay(_)
+                        | api_models::payments::WalletData::TwintRedirect {}
+                        | api_models::payments::WalletData::VippsRedirect {}
+                        | api_models::payments::WalletData::TouchNGoRedirect(_)
+                        | api_models::payments::WalletData::WeChatPayRedirect(_)
+                        | api_models::payments::WalletData::WeChatPayQr(_)
+                        | api_models::payments::WalletData::CashappQr(_)
+                        | api_models::payments::WalletData::SwishQr(_) => {
+                            Err(errors::ConnectorError::NotSupported {
+                                message: conn_utils::SELECTED_PAYMENT_METHOD.to_string(),
+                                connector: "Noon",
+                            })
+                        }
                     },
-                    _ => Err(errors::ConnectorError::NotImplemented(
-                        "Payment methods".to_string(),
-                    )),
+                    api::PaymentMethodData::CardRedirect(_)
+                    | api::PaymentMethodData::PayLater(_)
+                    | api::PaymentMethodData::BankRedirect(_)
+                    | api::PaymentMethodData::BankDebit(_)
+                    | api::PaymentMethodData::BankTransfer(_)
+                    | api::PaymentMethodData::Crypto(_)
+                    | api::PaymentMethodData::MandatePayment {}
+                    | api::PaymentMethodData::Reward {}
+                    | api::PaymentMethodData::Upi(_)
+                    | api::PaymentMethodData::Voucher(_)
+                    | api::PaymentMethodData::GiftCard(_) => {
+                        Err(errors::ConnectorError::NotSupported {
+                            message: conn_utils::SELECTED_PAYMENT_METHOD.to_string(),
+                            connector: "Noon",
+                        })
+                    }
                 }?,
                 Some(item.request.currency),
                 item.request.order_category.clone(),
@@ -473,6 +511,7 @@ impl<F, T>
                     message: error_message.clone(),
                     reason: Some(error_message),
                     status_code: item.http_code,
+                    attempt_status: None,
                 }),
                 _ => {
                     let connector_response_reference_id =
diff --git a/crates/router/src/connector/nuvei.rs b/crates/router/src/connector/nuvei.rs
index 754ba5ff7443..15702829d378 100644
--- a/crates/router/src/connector/nuvei.rs
+++ b/crates/router/src/connector/nuvei.rs
@@ -149,6 +149,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCompleteAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let meta: nuvei::NuveiMeta = utils::to_connector_meta(req.request.connector_meta.clone())?;
         let req_obj = nuvei::NuveiPaymentsRequest::try_from((req, meta.session_token))?;
@@ -176,7 +177,7 @@ impl
                     self, req, connectors,
                 )?)
                 .body(types::PaymentsCompleteAuthorizeType::get_request_body(
-                    self, req,
+                    self, req, connectors,
                 )?)
                 .build(),
         ))
@@ -235,6 +236,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = nuvei::NuveiPaymentFlowRequest::try_from(req)?;
         let req = types::RequestBody::log_and_get_request_body(
@@ -255,7 +257,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
             .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
             .attach_default_headers()
             .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-            .body(types::PaymentsVoidType::get_request_body(self, req)?)
+            .body(types::PaymentsVoidType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -319,6 +323,7 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
     fn get_request_body(
         &self,
         req: &types::PaymentsSyncRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = nuvei::NuveiPaymentSyncRequest::try_from(req)?;
         let req = types::RequestBody::log_and_get_request_body(
@@ -339,7 +344,9 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
                 .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsSyncType::get_request_body(self, req)?)
+                .body(types::PaymentsSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -398,6 +405,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = nuvei::NuveiPaymentFlowRequest::try_from(req)?;
         let req = types::RequestBody::log_and_get_request_body(
@@ -421,7 +429,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -555,6 +565,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = nuvei::NuveiPaymentsRequest::try_from((req, req.get_session_token()?))?;
         let req = types::RequestBody::log_and_get_request_body(
@@ -581,7 +592,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -644,6 +657,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeSessionTokenRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = nuvei::NuveiSessionRequest::try_from(req)?;
         let req = types::RequestBody::log_and_get_request_body(
@@ -670,7 +684,7 @@ impl
                     self, req, connectors,
                 )?)
                 .body(types::PaymentsPreAuthorizeType::get_request_body(
-                    self, req,
+                    self, req, connectors,
                 )?)
                 .build(),
         ))
@@ -727,6 +741,7 @@ impl ConnectorIntegration<InitPayment, types::PaymentsAuthorizeData, types::Paym
     fn get_request_body(
         &self,
         req: &types::PaymentsInitRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = nuvei::NuveiPaymentsRequest::try_from((req, req.get_session_token()?))?;
         let req = types::RequestBody::log_and_get_request_body(
@@ -749,7 +764,9 @@ impl ConnectorIntegration<InitPayment, types::PaymentsAuthorizeData, types::Paym
                 .url(&types::PaymentsInitType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsInitType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsInitType::get_request_body(self, req)?)
+                .body(types::PaymentsInitType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -806,6 +823,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = nuvei::NuveiPaymentFlowRequest::try_from(req)?;
         let req = types::RequestBody::log_and_get_request_body(
@@ -828,7 +846,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/nuvei/transformers.rs b/crates/router/src/connector/nuvei/transformers.rs
index 88ebe1d8dbea..c23114e2a96b 100644
--- a/crates/router/src/connector/nuvei/transformers.rs
+++ b/crates/router/src/connector/nuvei/transformers.rs
@@ -1579,6 +1579,7 @@ fn get_error_response<T>(
             .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
         reason: None,
         status_code: http_code,
+        attempt_status: None,
     })
 }
 
diff --git a/crates/router/src/connector/opayo.rs b/crates/router/src/connector/opayo.rs
index 89e16416d27f..cc517ca1f3b8 100644
--- a/crates/router/src/connector/opayo.rs
+++ b/crates/router/src/connector/opayo.rs
@@ -107,6 +107,7 @@ impl ConnectorCommon for Opayo {
             code: response.code,
             message: response.message,
             reason: response.reason,
+            attempt_status: None,
         })
     }
 }
@@ -172,6 +173,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = opayo::OpayoPaymentsRequest::try_from(req)?;
         let opayo_req = types::RequestBody::log_and_get_request_body(
@@ -197,7 +199,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -314,6 +318,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         _req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into())
     }
@@ -331,7 +336,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -389,6 +396,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = opayo::OpayoRefundRequest::try_from(req)?;
 
@@ -412,7 +420,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -473,7 +483,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/opayo/transformers.rs b/crates/router/src/connector/opayo/transformers.rs
index d828232dbc1a..41bcc1500ed1 100644
--- a/crates/router/src/connector/opayo/transformers.rs
+++ b/crates/router/src/connector/opayo/transformers.rs
@@ -2,7 +2,7 @@ use masking::Secret;
 use serde::{Deserialize, Serialize};
 
 use crate::{
-    connector::utils::PaymentsAuthorizeRequestData,
+    connector::utils::{self, PaymentsAuthorizeRequestData},
     core::errors,
     types::{self, api, storage::enums},
 };
@@ -41,7 +41,21 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for OpayoPaymentsRequest {
                     card,
                 })
             }
-            _ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()),
+            api::PaymentMethodData::CardRedirect(_)
+            | api::PaymentMethodData::Wallet(_)
+            | api::PaymentMethodData::PayLater(_)
+            | api::PaymentMethodData::BankRedirect(_)
+            | api::PaymentMethodData::BankDebit(_)
+            | api::PaymentMethodData::BankTransfer(_)
+            | api::PaymentMethodData::Crypto(_)
+            | api::PaymentMethodData::MandatePayment
+            | api::PaymentMethodData::Reward
+            | api::PaymentMethodData::Upi(_)
+            | api::PaymentMethodData::Voucher(_)
+            | api::PaymentMethodData::GiftCard(_) => Err(errors::ConnectorError::NotImplemented(
+                utils::get_unimplemented_payment_method_error_message("Opayo"),
+            )
+            .into()),
         }
     }
 }
diff --git a/crates/router/src/connector/opennode.rs b/crates/router/src/connector/opennode.rs
index 6fad0f472050..3151403a5534 100644
--- a/crates/router/src/connector/opennode.rs
+++ b/crates/router/src/connector/opennode.rs
@@ -72,6 +72,10 @@ impl ConnectorCommon for Opennode {
         "opennode"
     }
 
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Minor
+    }
+
     fn common_get_content_type(&self) -> &'static str {
         "application/json"
     }
@@ -106,6 +110,7 @@ impl ConnectorCommon for Opennode {
             code: consts::NO_ERROR_CODE.to_string(),
             message: response.message,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -168,8 +173,15 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let req_obj = opennode::OpennodePaymentsRequest::try_from(req)?;
+        let connector_router_data = opennode::OpennodeRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+        let req_obj = opennode::OpennodePaymentsRequest::try_from(&connector_router_data)?;
         let opennode_req = types::RequestBody::log_and_get_request_body(
             &req_obj,
             Encode::<opennode::OpennodePaymentsRequest>::encode_to_string_of_json,
@@ -192,7 +204,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/opennode/transformers.rs b/crates/router/src/connector/opennode/transformers.rs
index aa3fae3a5164..794fc8573417 100644
--- a/crates/router/src/connector/opennode/transformers.rs
+++ b/crates/router/src/connector/opennode/transformers.rs
@@ -10,6 +10,37 @@ use crate::{
     types::{self, api, storage::enums},
 };
 
+#[derive(Debug, Serialize)]
+pub struct OpennodeRouterData<T> {
+    pub amount: i64,
+    pub router_data: T,
+}
+
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for OpennodeRouterData<T>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+
+    fn try_from(
+        (_currency_unit, _currency, amount, router_data): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            amount,
+            router_data,
+        })
+    }
+}
+
 //TODO: Fill the struct with respective fields
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 pub struct OpennodePaymentsRequest {
@@ -19,11 +50,14 @@ pub struct OpennodePaymentsRequest {
     auto_settle: bool,
     success_url: String,
     callback_url: String,
+    order_id: String,
 }
 
-impl TryFrom<&types::PaymentsAuthorizeRouterData> for OpennodePaymentsRequest {
+impl TryFrom<&OpennodeRouterData<&types::PaymentsAuthorizeRouterData>> for OpennodePaymentsRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
+    fn try_from(
+        item: &OpennodeRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
         get_crypto_specific_payment_data(item)
     }
 }
@@ -145,11 +179,13 @@ pub struct OpennodeRefundRequest {
     pub amount: i64,
 }
 
-impl<F> TryFrom<&types::RefundsRouterData<F>> for OpennodeRefundRequest {
+impl<F> TryFrom<&OpennodeRouterData<&types::RefundsRouterData<F>>> for OpennodeRefundRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
+    fn try_from(
+        item: &OpennodeRouterData<&types::RefundsRouterData<F>>,
+    ) -> Result<Self, Self::Error> {
         Ok(Self {
-            amount: item.request.refund_amount,
+            amount: item.router_data.request.refund_amount,
         })
     }
 }
@@ -221,14 +257,15 @@ pub struct OpennodeErrorResponse {
 }
 
 fn get_crypto_specific_payment_data(
-    item: &types::PaymentsAuthorizeRouterData,
+    item: &OpennodeRouterData<&types::PaymentsAuthorizeRouterData>,
 ) -> Result<OpennodePaymentsRequest, error_stack::Report<errors::ConnectorError>> {
-    let amount = item.request.amount;
-    let currency = item.request.currency.to_string();
-    let description = item.get_description()?;
+    let amount = item.amount;
+    let currency = item.router_data.request.currency.to_string();
+    let description = item.router_data.get_description()?;
     let auto_settle = true;
-    let success_url = item.get_return_url()?;
-    let callback_url = item.request.get_webhook_url()?;
+    let success_url = item.router_data.get_return_url()?;
+    let callback_url = item.router_data.request.get_webhook_url()?;
+    let order_id = item.router_data.connector_request_reference_id.clone();
 
     Ok(OpennodePaymentsRequest {
         amount,
@@ -237,6 +274,7 @@ fn get_crypto_specific_payment_data(
         auto_settle,
         success_url,
         callback_url,
+        order_id,
     })
 }
 
diff --git a/crates/router/src/connector/payeezy.rs b/crates/router/src/connector/payeezy.rs
index da7126054378..8bb8eaa8b4c2 100644
--- a/crates/router/src/connector/payeezy.rs
+++ b/crates/router/src/connector/payeezy.rs
@@ -39,10 +39,10 @@ where
     fn build_headers(
         &self,
         req: &types::RouterData<Flow, Request, Response>,
-        _connectors: &settings::Connectors,
+        connectors: &settings::Connectors,
     ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
         let auth = payeezy::PayeezyAuthType::try_from(&req.connector_auth_type)?;
-        let option_request_payload = self.get_request_body(req)?;
+        let option_request_payload = self.get_request_body(req, connectors)?;
         let request_payload = option_request_payload.map_or("{}".to_string(), |payload| {
             types::RequestBody::get_inner_value(payload).expose()
         });
@@ -90,6 +90,10 @@ impl ConnectorCommon for Payeezy {
         "payeezy"
     }
 
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Base
+    }
+
     fn common_get_content_type(&self) -> &'static str {
         "application/json"
     }
@@ -119,6 +123,7 @@ impl ConnectorCommon for Payeezy {
             code: response.transaction_status,
             message: error_messages.join(", "),
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -195,6 +200,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = payeezy::PayeezyCaptureOrVoidRequest::try_from(req)?;
         let payeezy_req = types::RequestBody::log_and_get_request_body(
@@ -215,7 +221,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .method(services::Method::Post)
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -291,13 +299,21 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let connector_req = payeezy::PayeezyCaptureOrVoidRequest::try_from(req)?;
+        let router_obj = payeezy::PayeezyRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount_to_capture,
+            req,
+        ))?;
+        let req_obj = payeezy::PayeezyCaptureOrVoidRequest::try_from(&router_obj)?;
         let payeezy_req = types::RequestBody::log_and_get_request_body(
-            &connector_req,
+            &req_obj,
             utils::Encode::<payeezy::PayeezyCaptureOrVoidRequest>::encode_to_string_of_json,
         )
         .change_context(errors::ConnectorError::RequestEncodingFailed)?;
+
         Ok(Some(payeezy_req))
     }
 
@@ -313,7 +329,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -379,10 +397,18 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let connector_req = payeezy::PayeezyPaymentsRequest::try_from(req)?;
+        let router_obj = payeezy::PayeezyRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+        let req_obj = payeezy::PayeezyPaymentsRequest::try_from(&router_obj)?;
+
         let payeezy_req = types::RequestBody::log_and_get_request_body(
-            &connector_req,
+            &req_obj,
             utils::Encode::<payeezy::PayeezyPaymentsRequest>::encode_to_string_of_json,
         )
         .change_context(errors::ConnectorError::RequestEncodingFailed)?;
@@ -403,7 +429,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -468,11 +496,18 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let connector_req = payeezy::PayeezyRefundRequest::try_from(req)?;
+        let router_obj = payeezy::PayeezyRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.refund_amount,
+            req,
+        ))?;
+        let req_obj = payeezy::PayeezyRefundRequest::try_from(&router_obj)?;
         let payeezy_req = types::RequestBody::log_and_get_request_body(
-            &connector_req,
-            utils::Encode::<payeezy::PayeezyCaptureOrVoidRequest>::encode_to_string_of_json,
+            &req_obj,
+            utils::Encode::<payeezy::PayeezyRefundRequest>::encode_to_string_of_json,
         )
         .change_context(errors::ConnectorError::RequestEncodingFailed)?;
         Ok(Some(payeezy_req))
@@ -489,7 +524,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -499,16 +536,22 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
         data: &types::RefundsRouterData<api::Execute>,
         res: Response,
     ) -> CustomResult<types::RefundsRouterData<api::Execute>, errors::ConnectorError> {
+        // Parse the response into a payeezy::RefundResponse
         let response: payeezy::RefundResponse = res
             .response
             .parse_struct("payeezy RefundResponse")
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
-        types::RefundsRouterData::try_from(types::ResponseRouterData {
+
+        // Create a new instance of types::RefundsRouterData based on the response, input data, and HTTP code
+        let response_data = types::ResponseRouterData {
             response,
             data: data.clone(),
             http_code: res.status_code,
-        })
-        .change_context(errors::ConnectorError::ResponseHandlingFailed)
+        };
+        let router_data = types::RefundsRouterData::try_from(response_data)
+            .change_context(errors::ConnectorError::ResponseHandlingFailed)?;
+
+        Ok(router_data)
     }
 
     fn get_error_response(
diff --git a/crates/router/src/connector/payeezy/transformers.rs b/crates/router/src/connector/payeezy/transformers.rs
index 98e8ea12c00d..3a859b325300 100644
--- a/crates/router/src/connector/payeezy/transformers.rs
+++ b/crates/router/src/connector/payeezy/transformers.rs
@@ -9,6 +9,37 @@ use crate::{
     core::errors,
     types::{self, api, storage::enums, transformers::ForeignFrom},
 };
+#[derive(Debug, Serialize)]
+pub struct PayeezyRouterData<T> {
+    pub amount: String,
+    pub router_data: T,
+}
+
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for PayeezyRouterData<T>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+
+    fn try_from(
+        (currency_unit, currency, amount, router_data): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        let amount = utils::get_amount_as_string(currency_unit, amount, currency)?;
+        Ok(Self {
+            amount,
+            router_data,
+        })
+    }
+}
 
 #[derive(Serialize, Debug)]
 pub struct PayeezyCard {
@@ -37,11 +68,14 @@ impl TryFrom<utils::CardIssuer> for PayeezyCardType {
             utils::CardIssuer::Master => Ok(Self::Mastercard),
             utils::CardIssuer::Discover => Ok(Self::Discover),
             utils::CardIssuer::Visa => Ok(Self::Visa),
-            _ => Err(errors::ConnectorError::NotSupported {
-                message: issuer.to_string(),
-                connector: "Payeezy",
+
+            utils::CardIssuer::Maestro | utils::CardIssuer::DinersClub | utils::CardIssuer::JCB => {
+                Err(errors::ConnectorError::NotSupported {
+                    message: utils::SELECTED_PAYMENT_METHOD.to_string(),
+                    connector: "Payeezy",
+                }
+                .into())
             }
-            .into()),
         }
     }
 }
@@ -63,7 +97,7 @@ pub struct PayeezyPaymentsRequest {
     pub merchant_ref: String,
     pub transaction_type: PayeezyTransactionType,
     pub method: PayeezyPaymentMethodType,
-    pub amount: i64,
+    pub amount: String,
     pub currency_code: String,
     pub credit_card: PayeezyPaymentMethod,
     pub stored_credentials: Option<StoredCredentials>,
@@ -92,25 +126,41 @@ pub enum Initiator {
     CardHolder,
 }
 
-impl TryFrom<&types::PaymentsAuthorizeRouterData> for PayeezyPaymentsRequest {
+impl TryFrom<&PayeezyRouterData<&types::PaymentsAuthorizeRouterData>> for PayeezyPaymentsRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
-        match item.payment_method {
+    fn try_from(
+        item: &PayeezyRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
+        match item.router_data.payment_method {
             diesel_models::enums::PaymentMethod::Card => get_card_specific_payment_data(item),
-            _ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()),
+
+            diesel_models::enums::PaymentMethod::CardRedirect
+            | diesel_models::enums::PaymentMethod::PayLater
+            | diesel_models::enums::PaymentMethod::Wallet
+            | diesel_models::enums::PaymentMethod::BankRedirect
+            | diesel_models::enums::PaymentMethod::BankTransfer
+            | diesel_models::enums::PaymentMethod::Crypto
+            | diesel_models::enums::PaymentMethod::BankDebit
+            | diesel_models::enums::PaymentMethod::Reward
+            | diesel_models::enums::PaymentMethod::Upi
+            | diesel_models::enums::PaymentMethod::Voucher
+            | diesel_models::enums::PaymentMethod::GiftCard => {
+                Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into())
+            }
         }
     }
 }
 
 fn get_card_specific_payment_data(
-    item: &types::PaymentsAuthorizeRouterData,
+    item: &PayeezyRouterData<&types::PaymentsAuthorizeRouterData>,
 ) -> Result<PayeezyPaymentsRequest, error_stack::Report<errors::ConnectorError>> {
-    let merchant_ref = item.attempt_id.to_string();
+    let merchant_ref = item.router_data.attempt_id.to_string();
     let method = PayeezyPaymentMethodType::CreditCard;
-    let amount = item.request.amount;
-    let currency_code = item.request.currency.to_string();
+    let amount = item.amount.clone();
+    let currency_code = item.router_data.request.currency.to_string();
     let credit_card = get_payment_method_data(item)?;
-    let (transaction_type, stored_credentials) = get_transaction_type_and_stored_creds(item)?;
+    let (transaction_type, stored_credentials) =
+        get_transaction_type_and_stored_creds(item.router_data)?;
     Ok(PayeezyPaymentsRequest {
         merchant_ref,
         transaction_type,
@@ -119,7 +169,7 @@ fn get_card_specific_payment_data(
         currency_code,
         credit_card,
         stored_credentials,
-        reference: item.connector_request_reference_id.clone(),
+        reference: item.router_data.connector_request_reference_id.clone(),
     })
 }
 fn get_transaction_type_and_stored_creds(
@@ -165,7 +215,10 @@ fn get_transaction_type_and_stored_creds(
                 Some(diesel_models::enums::CaptureMethod::Automatic) => {
                     Ok((PayeezyTransactionType::Purchase, None))
                 }
-                _ => Err(errors::ConnectorError::FlowNotSupported {
+
+                Some(diesel_models::enums::CaptureMethod::ManualMultiple)
+                | Some(diesel_models::enums::CaptureMethod::Scheduled)
+                | None => Err(errors::ConnectorError::FlowNotSupported {
                     flow: item.request.capture_method.unwrap_or_default().to_string(),
                     connector: "Payeezy".to_string(),
                 }),
@@ -182,9 +235,9 @@ fn is_mandate_payment(
 }
 
 fn get_payment_method_data(
-    item: &types::PaymentsAuthorizeRouterData,
+    item: &PayeezyRouterData<&types::PaymentsAuthorizeRouterData>,
 ) -> Result<PayeezyPaymentMethod, error_stack::Report<errors::ConnectorError>> {
-    match item.request.payment_method_data {
+    match item.router_data.request.payment_method_data {
         api::PaymentMethodData::Card(ref card) => {
             let card_type = PayeezyCardType::try_from(card.get_card_issuer()?)?;
             let payeezy_card = PayeezyCard {
@@ -196,7 +249,23 @@ fn get_payment_method_data(
             };
             Ok(PayeezyPaymentMethod::PayeezyCard(payeezy_card))
         }
-        _ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()),
+
+        api::PaymentMethodData::CardRedirect(_)
+        | api::PaymentMethodData::Wallet(_)
+        | api::PaymentMethodData::PayLater(_)
+        | api::PaymentMethodData::BankRedirect(_)
+        | api::PaymentMethodData::BankDebit(_)
+        | api::PaymentMethodData::BankTransfer(_)
+        | api::PaymentMethodData::Crypto(_)
+        | api::PaymentMethodData::MandatePayment
+        | api::PaymentMethodData::Reward
+        | api::PaymentMethodData::Upi(_)
+        | api::PaymentMethodData::Voucher(_)
+        | api::PaymentMethodData::GiftCard(_) => Err(errors::ConnectorError::NotSupported {
+            message: utils::SELECTED_PAYMENT_METHOD.to_string(),
+            connector: "Payeezy",
+        }
+        .into()),
     }
 }
 
@@ -270,16 +339,20 @@ pub struct PayeezyCaptureOrVoidRequest {
     currency_code: String,
 }
 
-impl TryFrom<&types::PaymentsCaptureRouterData> for PayeezyCaptureOrVoidRequest {
+impl TryFrom<&PayeezyRouterData<&types::PaymentsCaptureRouterData>>
+    for PayeezyCaptureOrVoidRequest
+{
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsCaptureRouterData) -> Result<Self, Self::Error> {
+    fn try_from(
+        item: &PayeezyRouterData<&types::PaymentsCaptureRouterData>,
+    ) -> Result<Self, Self::Error> {
         let metadata: PayeezyPaymentsMetadata =
-            utils::to_connector_meta(item.request.connector_meta.clone())
+            utils::to_connector_meta(item.router_data.request.connector_meta.clone())
                 .change_context(errors::ConnectorError::RequestEncodingFailed)?;
         Ok(Self {
             transaction_type: PayeezyTransactionType::Capture,
-            amount: item.request.amount_to_capture.to_string(),
-            currency_code: item.request.currency.to_string(),
+            amount: item.amount.clone(),
+            currency_code: item.router_data.request.currency.to_string(),
             transaction_tag: metadata.transaction_tag,
         })
     }
@@ -303,6 +376,7 @@ impl TryFrom<&types::PaymentsCancelRouterData> for PayeezyCaptureOrVoidRequest {
         })
     }
 }
+
 #[derive(Debug, Deserialize, Serialize, Default)]
 #[serde(rename_all = "lowercase")]
 pub enum PayeezyTransactionType {
@@ -383,7 +457,7 @@ impl ForeignFrom<(PayeezyPaymentStatus, PayeezyTransactionType)> for enums::Atte
                 | PayeezyTransactionType::Purchase
                 | PayeezyTransactionType::Recurring => Self::Charged,
                 PayeezyTransactionType::Void => Self::Voided,
-                _ => Self::Pending,
+                PayeezyTransactionType::Refund | PayeezyTransactionType::Pending => Self::Pending,
             },
             PayeezyPaymentStatus::Declined | PayeezyPaymentStatus::NotProcessed => match method {
                 PayeezyTransactionType::Capture => Self::CaptureFailed,
@@ -391,7 +465,7 @@ impl ForeignFrom<(PayeezyPaymentStatus, PayeezyTransactionType)> for enums::Atte
                 | PayeezyTransactionType::Purchase
                 | PayeezyTransactionType::Recurring => Self::AuthorizationFailed,
                 PayeezyTransactionType::Void => Self::VoidFailed,
-                _ => Self::Pending,
+                PayeezyTransactionType::Refund | PayeezyTransactionType::Pending => Self::Pending,
             },
         }
     }
@@ -407,16 +481,18 @@ pub struct PayeezyRefundRequest {
     currency_code: String,
 }
 
-impl<F> TryFrom<&types::RefundsRouterData<F>> for PayeezyRefundRequest {
+impl<F> TryFrom<&PayeezyRouterData<&types::RefundsRouterData<F>>> for PayeezyRefundRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
+    fn try_from(
+        item: &PayeezyRouterData<&types::RefundsRouterData<F>>,
+    ) -> Result<Self, Self::Error> {
         let metadata: PayeezyPaymentsMetadata =
-            utils::to_connector_meta(item.request.connector_metadata.clone())
+            utils::to_connector_meta(item.router_data.request.connector_metadata.clone())
                 .change_context(errors::ConnectorError::RequestEncodingFailed)?;
         Ok(Self {
             transaction_type: PayeezyTransactionType::Refund,
-            amount: item.request.refund_amount.to_string(),
-            currency_code: item.request.currency.to_string(),
+            amount: item.amount.clone(),
+            currency_code: item.router_data.request.currency.to_string(),
             transaction_tag: metadata.transaction_tag,
         })
     }
diff --git a/crates/router/src/connector/payme.rs b/crates/router/src/connector/payme.rs
index e0d6229c004c..ef10c6d00878 100644
--- a/crates/router/src/connector/payme.rs
+++ b/crates/router/src/connector/payme.rs
@@ -97,6 +97,7 @@ impl ConnectorCommon for Payme {
                 "{}, additional info: {}",
                 response.status_error_details, response.status_additional_info
             )),
+            attempt_status: None,
         })
     }
 }
@@ -149,6 +150,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::TokenizationRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = payme::CaptureBuyerRequest::try_from(req)?;
 
@@ -172,7 +174,9 @@ impl
                     .url(&types::TokenizationType::get_url(self, req, connectors)?)
                     .attach_default_headers()
                     .headers(types::TokenizationType::get_headers(self, req, connectors)?)
-                    .body(types::TokenizationType::get_request_body(self, req)?)
+                    .body(types::TokenizationType::get_request_body(
+                        self, req, connectors,
+                    )?)
                     .build(),
             ),
             AuthenticationType::NoThreeDs => None,
@@ -252,6 +256,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsPreProcessingRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let amount = req.request.get_amount()?;
         let currency = req.request.get_currency()?;
@@ -282,7 +287,7 @@ impl
                     self, req, connectors,
                 )?)
                 .body(types::PaymentsPreProcessingType::get_request_body(
-                    self, req,
+                    self, req, connectors,
                 )?)
                 .build(),
         );
@@ -377,6 +382,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCompleteAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = payme::Pay3dsRequest::try_from(req)?;
         let payme_req = types::RequestBody::log_and_get_request_body(
@@ -402,7 +408,7 @@ impl
                     self, req, connectors,
                 )?)
                 .body(types::PaymentsCompleteAuthorizeType::get_request_body(
-                    self, req,
+                    self, req, connectors,
                 )?)
                 .build(),
         ))
@@ -479,6 +485,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = payme::PaymeRouterData::try_from((
             &self.get_currency_unit(),
@@ -510,7 +517,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -573,6 +582,7 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
     fn get_request_body(
         &self,
         req: &types::RouterData<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = payme::PaymeQuerySaleRequest::try_from(req)?;
         let payme_req = types::RequestBody::log_and_get_request_body(
@@ -594,7 +604,9 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
                 .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsSyncType::get_request_body(self, req)?)
+                .body(types::PaymentsSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -658,6 +670,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = payme::PaymeRouterData::try_from((
             &self.get_currency_unit(),
@@ -687,7 +700,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -764,6 +779,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = payme::PaymeRouterData::try_from((
             &self.get_currency_unit(),
@@ -792,7 +808,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -853,6 +871,7 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
     fn get_request_body(
         &self,
         req: &types::RouterData<api::RSync, types::RefundsData, types::RefundsResponseData>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = payme::PaymeQueryTransactionRequest::try_from(req)?;
         let payme_req = types::RequestBody::log_and_get_request_body(
@@ -873,7 +892,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
             .url(&types::RefundSyncType::get_url(self, req, connectors)?)
             .attach_default_headers()
             .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-            .body(types::RefundSyncType::get_request_body(self, req)?)
+            .body(types::RefundSyncType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/payme/transformers.rs b/crates/router/src/connector/payme/transformers.rs
index 4ced1a9bcda3..24b7f2b3a0bd 100644
--- a/crates/router/src/connector/payme/transformers.rs
+++ b/crates/router/src/connector/payme/transformers.rs
@@ -226,6 +226,7 @@ impl From<(&PaymePaySaleResponse, u16)> for types::ErrorResponse {
                 .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
             reason: pay_sale_response.status_error_details.to_owned(),
             status_code: http_code,
+            attempt_status: None,
         }
     }
 }
@@ -308,6 +309,7 @@ impl From<(&SaleQuery, u16)> for types::ErrorResponse {
                 .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
             reason: sale_query_response.sale_error_text.clone(),
             status_code: http_code,
+            attempt_status: None,
         }
     }
 }
@@ -651,7 +653,20 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PayRequest {
                     language: LANGUAGE.to_string(),
                 })
             }
-            _ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()),
+            api::PaymentMethodData::CardRedirect(_)
+            | api::PaymentMethodData::Wallet(_)
+            | api::PaymentMethodData::PayLater(_)
+            | api::PaymentMethodData::BankRedirect(_)
+            | api::PaymentMethodData::BankDebit(_)
+            | api::PaymentMethodData::BankTransfer(_)
+            | api::PaymentMethodData::Crypto(_)
+            | api::PaymentMethodData::MandatePayment
+            | api::PaymentMethodData::Reward
+            | api::PaymentMethodData::Upi(_)
+            | api::PaymentMethodData::Voucher(_)
+            | api::PaymentMethodData::GiftCard(_) => Err(errors::ConnectorError::NotImplemented(
+                utils::get_unimplemented_payment_method_error_message("payme"),
+            ))?,
         }
     }
 }
diff --git a/crates/router/src/connector/paypal.rs b/crates/router/src/connector/paypal.rs
index 120795bef9c5..d4ab481eb9de 100644
--- a/crates/router/src/connector/paypal.rs
+++ b/crates/router/src/connector/paypal.rs
@@ -91,6 +91,7 @@ impl Paypal {
             code: response.name,
             message: response.message.clone(),
             reason: error_reason.or(Some(response.message)),
+            attempt_status: None,
         })
     }
 }
@@ -190,16 +191,20 @@ impl ConnectorCommon for Paypal {
                     })
             })
             .transpose()?;
-        let reason = error_reason
-            .unwrap_or(response.message.to_owned())
-            .is_empty()
-            .then_some(response.message.to_owned());
+        let reason = match error_reason {
+            Some(err_reason) => err_reason
+                .is_empty()
+                .then(|| response.message.to_owned())
+                .or(Some(err_reason)),
+            None => Some(response.message.to_owned()),
+        };
 
         Ok(ErrorResponse {
             status_code: res.status_code,
             code: response.name,
             message: response.message.clone(),
             reason,
+            attempt_status: None,
         })
     }
 }
@@ -278,6 +283,7 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
     fn get_request_body(
         &self,
         req: &types::RefreshTokenRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = paypal::PaypalAuthUpdateRequest::try_from(req)?;
         let paypal_req = types::RequestBody::log_and_get_request_body(
@@ -299,7 +305,9 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
                 .method(services::Method::Post)
                 .headers(types::RefreshTokenType::get_headers(self, req, connectors)?)
                 .url(&types::RefreshTokenType::get_url(self, req, connectors)?)
-                .body(types::RefreshTokenType::get_request_body(self, req)?)
+                .body(types::RefreshTokenType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         );
 
@@ -337,6 +345,7 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
             code: response.error,
             message: response.error_description.clone(),
             reason: Some(response.error_description),
+            attempt_status: None,
         })
     }
 }
@@ -376,6 +385,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = paypal::PaypalRouterData::try_from((
             &self.get_currency_unit(),
@@ -409,7 +419,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -511,7 +523,7 @@ impl
                     self, req, connectors,
                 )?)
                 .body(types::PaymentsCompleteAuthorizeType::get_request_body(
-                    self, req,
+                    self, req, connectors,
                 )?)
                 .build(),
         ))
@@ -683,6 +695,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = paypal::PaypalRouterData::try_from((
             &self.get_currency_unit(),
@@ -711,7 +724,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -844,6 +859,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = paypal::PaypalRouterData::try_from((
             &self.get_currency_unit(),
@@ -871,7 +887,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
 
         Ok(Some(request))
@@ -1033,7 +1051,9 @@ impl
             .headers(types::VerifyWebhookSourceType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::VerifyWebhookSourceType::get_request_body(self, req)?)
+            .body(types::VerifyWebhookSourceType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
 
         Ok(Some(request))
@@ -1046,6 +1066,7 @@ impl
             types::VerifyWebhookSourceRequestData,
             types::VerifyWebhookSourceResponseData,
         >,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = paypal::PaypalSourceVerificationRequest::try_from(&req.request)?;
         let paypal_req = types::RequestBody::log_and_get_request_body(
diff --git a/crates/router/src/connector/payu.rs b/crates/router/src/connector/payu.rs
index 6433735f7c53..9a8d4734f837 100644
--- a/crates/router/src/connector/payu.rs
+++ b/crates/router/src/connector/payu.rs
@@ -96,6 +96,7 @@ impl ConnectorCommon for Payu {
             code: response.status.status_code,
             message: response.status.status_desc,
             reason: response.status.code_literal,
+            attempt_status: None,
         })
     }
 }
@@ -243,6 +244,7 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
     fn get_request_body(
         &self,
         req: &types::RefreshTokenRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = payu::PayuAuthUpdateRequest::try_from(req)?;
         let payu_req = types::RequestBody::log_and_get_request_body(
@@ -265,7 +267,9 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
                 .attach_default_headers()
                 .headers(types::RefreshTokenType::get_headers(self, req, connectors)?)
                 .url(&types::RefreshTokenType::get_url(self, req, connectors)?)
-                .body(types::RefreshTokenType::get_request_body(self, req)?)
+                .body(types::RefreshTokenType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         );
 
@@ -304,6 +308,7 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
             code: response.error,
             message: response.error_description,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -416,6 +421,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = payu::PayuPaymentsCaptureRequest::try_from(req)?;
         let payu_req = types::RequestBody::log_and_get_request_body(
@@ -439,7 +445,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -510,6 +518,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = payu::PayuPaymentsRequest::try_from(req)?;
         let payu_req = types::RequestBody::log_and_get_request_body(
@@ -539,7 +548,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -604,6 +615,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = payu::PayuRefundRequest::try_from(req)?;
         let payu_req = types::RequestBody::log_and_get_request_body(
@@ -626,7 +638,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/powertranz.rs b/crates/router/src/connector/powertranz.rs
index bcbe2113f616..04851dd1781a 100644
--- a/crates/router/src/connector/powertranz.rs
+++ b/crates/router/src/connector/powertranz.rs
@@ -120,6 +120,7 @@ impl ConnectorCommon for Powertranz {
             code: consts::NO_ERROR_CODE.to_string(),
             message: consts::NO_ERROR_MESSAGE.to_string(),
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -193,6 +194,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = powertranz::PowertranzPaymentsRequest::try_from(req)?;
         let powertranz_req = types::RequestBody::log_and_get_request_body(
@@ -218,7 +220,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -277,6 +281,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCompleteAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let redirect_payload: powertranz::RedirectResponsePayload = req
             .request
@@ -308,7 +313,7 @@ impl
                     self, req, connectors,
                 )?)
                 .body(types::PaymentsCompleteAuthorizeType::get_request_body(
-                    self, req,
+                    self, req, connectors,
                 )?)
                 .build(),
         ))
@@ -370,6 +375,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = powertranz::PowertranzBaseRequest::try_from(&req.request)?;
         let powertranz_req = types::RequestBody::log_and_get_request_body(
@@ -393,7 +399,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -444,6 +452,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::RouterData<api::Void, types::PaymentsCancelData, types::PaymentsResponseData>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = powertranz::PowertranzBaseRequest::try_from(&req.request)?;
         let powertranz_req = types::RequestBody::log_and_get_request_body(
@@ -481,7 +490,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsVoidType::get_request_body(self, req)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -520,6 +531,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = powertranz::PowertranzBaseRequest::try_from(req)?;
         let powertranz_req = types::RequestBody::log_and_get_request_body(
@@ -542,7 +554,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/powertranz/transformers.rs b/crates/router/src/connector/powertranz/transformers.rs
index 4032f8019b09..83bca662ec21 100644
--- a/crates/router/src/connector/powertranz/transformers.rs
+++ b/crates/router/src/connector/powertranz/transformers.rs
@@ -1,6 +1,7 @@
 use api_models::payments::Card;
 use common_utils::pii::Email;
 use diesel_models::enums::RefundStatus;
+use error_stack::IntoReport;
 use masking::Secret;
 use serde::{Deserialize, Serialize};
 use uuid::Uuid;
@@ -101,9 +102,22 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PowertranzPaymentsRequest
     fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
         let source = match item.request.payment_method_data.clone() {
             api::PaymentMethodData::Card(card) => Ok(Source::from(&card)),
-            _ => Err(errors::ConnectorError::NotImplemented(
-                "Payment method".to_string(),
-            )),
+            api::PaymentMethodData::Wallet(_)
+            | api::PaymentMethodData::CardRedirect(_)
+            | api::PaymentMethodData::PayLater(_)
+            | api::PaymentMethodData::BankRedirect(_)
+            | api::PaymentMethodData::BankDebit(_)
+            | api::PaymentMethodData::BankTransfer(_)
+            | api::PaymentMethodData::Crypto(_)
+            | api::PaymentMethodData::MandatePayment
+            | api::PaymentMethodData::Reward
+            | api::PaymentMethodData::Upi(_)
+            | api::PaymentMethodData::Voucher(_)
+            | api::PaymentMethodData::GiftCard(_) => Err(errors::ConnectorError::NotSupported {
+                message: utils::SELECTED_PAYMENT_METHOD.to_string(),
+                connector: "powertranz",
+            })
+            .into_report(),
         }?;
         // let billing_address = get_address_details(&item.address.billing, &item.request.email);
         // let shipping_address = get_address_details(&item.address.shipping, &item.request.email);
@@ -429,6 +443,7 @@ fn build_error_response(
                         .collect::<Vec<_>>()
                         .join(", "),
                 ),
+                attempt_status: None,
             }
         })
     } else if !ISO_SUCCESS_CODES.contains(&item.iso_response_code.as_str()) {
@@ -438,6 +453,7 @@ fn build_error_response(
             code: item.iso_response_code.clone(),
             message: item.response_message.clone(),
             reason: Some(item.response_message.clone()),
+            attempt_status: None,
         })
     } else {
         None
diff --git a/crates/router/src/connector/prophetpay.rs b/crates/router/src/connector/prophetpay.rs
index 288b4397e1d5..a7d735c5808b 100644
--- a/crates/router/src/connector/prophetpay.rs
+++ b/crates/router/src/connector/prophetpay.rs
@@ -117,6 +117,7 @@ impl ConnectorCommon for Prophetpay {
             code: response.status.to_string(),
             message: response.title,
             reason: Some(response.errors.to_string()),
+            attempt_status: None,
         })
     }
 }
@@ -174,6 +175,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = prophetpay::ProphetpayRouterData::try_from((
             &self.get_currency_unit(),
@@ -206,7 +208,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -473,6 +477,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
                 .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
+                .body(types::PaymentsVoidType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -530,6 +537,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = prophetpay::ProphetpayRouterData::try_from((
             &self.get_currency_unit(),
@@ -558,7 +566,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -638,7 +648,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/rapyd.rs b/crates/router/src/connector/rapyd.rs
index 292e6c55f26f..cd8893d0d7b1 100644
--- a/crates/router/src/connector/rapyd.rs
+++ b/crates/router/src/connector/rapyd.rs
@@ -64,6 +64,10 @@ impl ConnectorCommon for Rapyd {
         "rapyd"
     }
 
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Minor
+    }
+
     fn common_get_content_type(&self) -> &'static str {
         "application/json"
     }
@@ -94,6 +98,7 @@ impl ConnectorCommon for Rapyd {
                 code: response_data.status.error_code,
                 message: response_data.status.status.unwrap_or_default(),
                 reason: response_data.status.message,
+                attempt_status: None,
             }),
             Err(error_msg) => {
                 logger::error!(deserialization_error =? error_msg);
@@ -178,8 +183,15 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let req_obj = rapyd::RapydPaymentsRequest::try_from(req)?;
+        let connector_router_data = rapyd::RapydRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+        let req_obj = rapyd::RapydPaymentsRequest::try_from(&connector_router_data)?;
         let rapyd_req = types::RequestBody::log_and_get_request_body(
             &req_obj,
             utils::Encode::<rapyd::RapydPaymentsRequest>::encode_to_string_of_json,
@@ -201,7 +213,7 @@ impl
         let salt = Alphanumeric.sample_string(&mut rand::thread_rng(), 12);
 
         let auth: rapyd::RapydAuthType = rapyd::RapydAuthType::try_from(&req.connector_auth_type)?;
-        let body = types::PaymentsAuthorizeType::get_request_body(self, req)?
+        let body = types::PaymentsAuthorizeType::get_request_body(self, req, connectors)?
             .ok_or(errors::ConnectorError::RequestEncodingFailed)?;
         let req_body = types::RequestBody::get_inner_value(body).expose();
         let signature =
@@ -222,7 +234,9 @@ impl
                 self, req, connectors,
             )?)
             .headers(headers)
-            .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+            .body(types::PaymentsAuthorizeType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -482,8 +496,15 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let req_obj = rapyd::CaptureRequest::try_from(req)?;
+        let connector_router_data = rapyd::RapydRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount_to_capture,
+            req,
+        ))?;
+        let req_obj = rapyd::CaptureRequest::try_from(&connector_router_data)?;
         let rapyd_req = types::RequestBody::log_and_get_request_body(
             &req_obj,
             utils::Encode::<rapyd::CaptureRequest>::encode_to_string_of_json,
@@ -505,7 +526,7 @@ impl
             "/v1/payments/{}/capture",
             req.request.connector_transaction_id
         );
-        let body = types::PaymentsCaptureType::get_request_body(self, req)?
+        let body = types::PaymentsCaptureType::get_request_body(self, req, connectors)?
             .ok_or(errors::ConnectorError::RequestEncodingFailed)?;
         let req_body = types::RequestBody::get_inner_value(body).expose();
         let signature =
@@ -524,7 +545,9 @@ impl
                 self, req, connectors,
             )?)
             .headers(headers)
-            .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+            .body(types::PaymentsCaptureType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -614,8 +637,15 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let req_obj = rapyd::RapydRefundRequest::try_from(req)?;
+        let connector_router_data = rapyd::RapydRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.refund_amount,
+            req,
+        ))?;
+        let req_obj = rapyd::RapydRefundRequest::try_from(&connector_router_data)?;
         let rapyd_req = types::RequestBody::log_and_get_request_body(
             &req_obj,
             utils::Encode::<rapyd::RapydRefundRequest>::encode_to_string_of_json,
@@ -633,7 +663,7 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
         let timestamp = date_time::now_unix_timestamp();
         let salt = Alphanumeric.sample_string(&mut rand::thread_rng(), 12);
 
-        let body = types::RefundExecuteType::get_request_body(self, req)?
+        let body = types::RefundExecuteType::get_request_body(self, req, connectors)?
             .ok_or(errors::ConnectorError::RequestEncodingFailed)?;
         let req_body = types::RequestBody::get_inner_value(body).expose();
         let auth: rapyd::RapydAuthType = rapyd::RapydAuthType::try_from(&req.connector_auth_type)?;
@@ -650,7 +680,9 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
             .url(&types::RefundExecuteType::get_url(self, req, connectors)?)
             .attach_default_headers()
             .headers(headers)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/rapyd/transformers.rs b/crates/router/src/connector/rapyd/transformers.rs
index 79ad6838ac35..08985ba022fc 100644
--- a/crates/router/src/connector/rapyd/transformers.rs
+++ b/crates/router/src/connector/rapyd/transformers.rs
@@ -13,6 +13,36 @@ use crate::{
     utils::OptionExt,
 };
 
+#[derive(Debug, Serialize)]
+pub struct RapydRouterData<T> {
+    pub amount: i64,
+    pub router_data: T,
+}
+
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for RapydRouterData<T>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        (_currency_unit, _currency, amount, item): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            amount,
+            router_data: item,
+        })
+    }
+}
+
 #[derive(Default, Debug, Serialize)]
 pub struct RapydPaymentsRequest {
     pub amount: i64,
@@ -69,18 +99,23 @@ pub struct RapydWallet {
     token: Option<String>,
 }
 
-impl TryFrom<&types::PaymentsAuthorizeRouterData> for RapydPaymentsRequest {
+impl TryFrom<&RapydRouterData<&types::PaymentsAuthorizeRouterData>> for RapydPaymentsRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
-        let (capture, payment_method_options) = match item.payment_method {
+    fn try_from(
+        item: &RapydRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
+        let (capture, payment_method_options) = match item.router_data.payment_method {
             diesel_models::enums::PaymentMethod::Card => {
-                let three_ds_enabled = matches!(item.auth_type, enums::AuthenticationType::ThreeDs);
+                let three_ds_enabled = matches!(
+                    item.router_data.auth_type,
+                    enums::AuthenticationType::ThreeDs
+                );
                 let payment_method_options = PaymentMethodOptions {
                     three_ds: three_ds_enabled,
                 };
                 (
                     Some(matches!(
-                        item.request.capture_method,
+                        item.router_data.request.capture_method,
                         Some(enums::CaptureMethod::Automatic) | None
                     )),
                     Some(payment_method_options),
@@ -88,7 +123,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for RapydPaymentsRequest {
             }
             _ => (None, None),
         };
-        let payment_method = match item.request.payment_method_data {
+        let payment_method = match item.router_data.request.payment_method_data {
             api_models::payments::PaymentMethodData::Card(ref ccard) => {
                 Some(PaymentMethod {
                     pm_type: "in_amex_card".to_owned(), //[#369] Map payment method type based on country
@@ -128,10 +163,10 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for RapydPaymentsRequest {
         .change_context(errors::ConnectorError::NotImplemented(
             "payment_method".to_owned(),
         ))?;
-        let return_url = item.request.get_return_url()?;
+        let return_url = item.router_data.request.get_return_url()?;
         Ok(Self {
-            amount: item.request.amount,
-            currency: item.request.currency,
+            amount: item.amount,
+            currency: item.router_data.request.currency,
             payment_method,
             capture,
             payment_method_options,
@@ -276,13 +311,17 @@ pub struct RapydRefundRequest {
     pub currency: Option<enums::Currency>,
 }
 
-impl<F> TryFrom<&types::RefundsRouterData<F>> for RapydRefundRequest {
+impl<F> TryFrom<&RapydRouterData<&types::RefundsRouterData<F>>> for RapydRefundRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
+    fn try_from(item: &RapydRouterData<&types::RefundsRouterData<F>>) -> Result<Self, Self::Error> {
         Ok(Self {
-            payment: item.request.connector_transaction_id.to_string(),
-            amount: Some(item.request.refund_amount),
-            currency: Some(item.request.currency),
+            payment: item
+                .router_data
+                .request
+                .connector_transaction_id
+                .to_string(),
+            amount: Some(item.amount),
+            currency: Some(item.router_data.request.currency),
         })
     }
 }
@@ -380,11 +419,13 @@ pub struct CaptureRequest {
     statement_descriptor: Option<String>,
 }
 
-impl TryFrom<&types::PaymentsCaptureRouterData> for CaptureRequest {
+impl TryFrom<&RapydRouterData<&types::PaymentsCaptureRouterData>> for CaptureRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsCaptureRouterData) -> Result<Self, Self::Error> {
+    fn try_from(
+        item: &RapydRouterData<&types::PaymentsCaptureRouterData>,
+    ) -> Result<Self, Self::Error> {
         Ok(Self {
-            amount: Some(item.request.amount_to_capture),
+            amount: Some(item.amount),
             receipt_email: None,
             statement_descriptor: None,
         })
@@ -416,6 +457,7 @@ impl<F, T>
                             status_code: item.http_code,
                             message: item.response.status.status.unwrap_or_default(),
                             reason: data.failure_message.to_owned(),
+                            attempt_status: None,
                         }),
                     ),
                     _ => {
@@ -456,6 +498,7 @@ impl<F, T>
                     status_code: item.http_code,
                     message: item.response.status.status.unwrap_or_default(),
                     reason: item.response.status.message,
+                    attempt_status: None,
                 }),
             ),
         };
diff --git a/crates/router/src/connector/shift4.rs b/crates/router/src/connector/shift4.rs
index a17546711f14..98eb895db548 100644
--- a/crates/router/src/connector/shift4.rs
+++ b/crates/router/src/connector/shift4.rs
@@ -99,6 +99,7 @@ impl ConnectorCommon for Shift4 {
                 .unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()),
             message: response.error.message,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -185,6 +186,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = shift4::Shift4PaymentsRequest::try_from(req)?;
         let req = types::RequestBody::log_and_get_request_body(
@@ -248,7 +250,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -473,6 +477,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsInitRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = shift4::Shift4PaymentsRequest::try_from(req)?;
         let req = types::RequestBody::log_and_get_request_body(
@@ -495,7 +500,9 @@ impl
                 .content_type(request::ContentType::FormUrlEncoded)
                 .attach_default_headers()
                 .headers(types::PaymentsInitType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsInitType::get_request_body(self, req)?)
+                .body(types::PaymentsInitType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -555,6 +562,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCompleteAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = shift4::Shift4PaymentsRequest::try_from(req)?;
         let req = types::RequestBody::log_and_get_request_body(
@@ -580,7 +588,7 @@ impl
                     self, req, connectors,
                 )?)
                 .body(types::PaymentsCompleteAuthorizeType::get_request_body(
-                    self, req,
+                    self, req, connectors,
                 )?)
                 .build(),
         ))
@@ -635,6 +643,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = shift4::Shift4RefundRequest::try_from(req)?;
         let shift4_req = types::RequestBody::log_and_get_request_body(
@@ -657,7 +666,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -725,7 +736,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/shift4/transformers.rs b/crates/router/src/connector/shift4/transformers.rs
index 23c91e48d8ca..0dd3b8583490 100644
--- a/crates/router/src/connector/shift4/transformers.rs
+++ b/crates/router/src/connector/shift4/transformers.rs
@@ -717,6 +717,7 @@ impl<T, F>
             types::PaymentsResponseData,
         >,
     ) -> Result<Self, Self::Error> {
+        let connector_id = types::ResponseId::ConnectorTransactionId(item.response.id.clone());
         Ok(Self {
             status: enums::AttemptStatus::foreign_from((
                 item.response.captured,
@@ -727,7 +728,7 @@ impl<T, F>
                 item.response.status,
             )),
             response: Ok(types::PaymentsResponseData::TransactionResponse {
-                resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
+                resource_id: connector_id,
                 redirection_data: item
                     .response
                     .flow
@@ -737,7 +738,7 @@ impl<T, F>
                 mandate_reference: None,
                 connector_metadata: None,
                 network_txn_id: None,
-                connector_response_reference_id: None,
+                connector_response_reference_id: Some(item.response.id),
             }),
             ..item.data
         })
diff --git a/crates/router/src/connector/square.rs b/crates/router/src/connector/square.rs
index a048b0f5433b..1d4d7e95dfa3 100644
--- a/crates/router/src/connector/square.rs
+++ b/crates/router/src/connector/square.rs
@@ -123,6 +123,7 @@ impl ConnectorCommon for Square {
                 .and_then(|error| error.category.clone())
                 .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
             reason: Some(reason),
+            attempt_status: None,
         })
     }
 }
@@ -245,6 +246,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::TokenizationRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = square::SquareTokenRequest::try_from(req)?;
 
@@ -267,7 +269,9 @@ impl
                 .url(&types::TokenizationType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::TokenizationType::get_headers(self, req, connectors)?)
-                .body(types::TokenizationType::get_request_body(self, req)?)
+                .body(types::TokenizationType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -412,6 +416,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = square::SquarePaymentsRequest::try_from(req)?;
 
@@ -438,7 +443,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -702,6 +709,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = square::SquareRefundRequest::try_from(req)?;
         let square_req = types::RequestBody::log_and_get_request_body(
@@ -724,7 +732,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/square/transformers.rs b/crates/router/src/connector/square/transformers.rs
index 01ed507bf34a..54a7c461dbfc 100644
--- a/crates/router/src/connector/square/transformers.rs
+++ b/crates/router/src/connector/square/transformers.rs
@@ -23,7 +23,10 @@ impl TryFrom<(&types::TokenizationRouterData, BankDebitData)> for SquareTokenReq
                 "Payment Method".to_string(),
             ))
             .into_report(),
-            _ => Err(errors::ConnectorError::NotSupported {
+
+            BankDebitData::SepaBankDebit { .. }
+            | BankDebitData::BecsBankDebit { .. }
+            | BankDebitData::BacsBankDebit { .. } => Err(errors::ConnectorError::NotSupported {
                 message: format!("{:?}", item.request.payment_method_data),
                 connector: "Square",
             })?,
@@ -85,7 +88,14 @@ impl TryFrom<(&types::TokenizationRouterData, PayLaterData)> for SquareTokenRequ
                 errors::ConnectorError::NotImplemented("Payment Method".to_string()),
             )
             .into_report(),
-            _ => Err(errors::ConnectorError::NotSupported {
+
+            PayLaterData::KlarnaRedirect { .. }
+            | PayLaterData::KlarnaSdk { .. }
+            | PayLaterData::AffirmRedirect { .. }
+            | PayLaterData::PayBrightRedirect { .. }
+            | PayLaterData::WalleyRedirect { .. }
+            | PayLaterData::AlmaRedirect { .. }
+            | PayLaterData::AtomeRedirect { .. } => Err(errors::ConnectorError::NotSupported {
                 message: format!("{:?}", item.request.payment_method_data),
                 connector: "Square",
             })?,
@@ -106,7 +116,31 @@ impl TryFrom<(&types::TokenizationRouterData, WalletData)> for SquareTokenReques
                 "Payment Method".to_string(),
             ))
             .into_report(),
-            _ => Err(errors::ConnectorError::NotSupported {
+
+            WalletData::AliPayQr(_)
+            | WalletData::AliPayRedirect(_)
+            | WalletData::AliPayHkRedirect(_)
+            | WalletData::MomoRedirect(_)
+            | WalletData::KakaoPayRedirect(_)
+            | WalletData::GoPayRedirect(_)
+            | WalletData::GcashRedirect(_)
+            | WalletData::ApplePayRedirect(_)
+            | WalletData::ApplePayThirdPartySdk(_)
+            | WalletData::DanaRedirect {}
+            | WalletData::GooglePayRedirect(_)
+            | WalletData::GooglePayThirdPartySdk(_)
+            | WalletData::MbWayRedirect(_)
+            | WalletData::MobilePayRedirect(_)
+            | WalletData::PaypalRedirect(_)
+            | WalletData::PaypalSdk(_)
+            | WalletData::SamsungPay(_)
+            | WalletData::TwintRedirect {}
+            | WalletData::VippsRedirect {}
+            | WalletData::TouchNGoRedirect(_)
+            | WalletData::WeChatPayRedirect(_)
+            | WalletData::WeChatPayQr(_)
+            | WalletData::CashappQr(_)
+            | WalletData::SwishQr(_) => Err(errors::ConnectorError::NotSupported {
                 message: format!("{:?}", item.request.payment_method_data),
                 connector: "Square",
             })?,
@@ -295,7 +329,14 @@ impl TryFrom<&types::ConnectorAuthType> for SquareAuthType {
                 api_key: api_key.to_owned(),
                 key1: key1.to_owned(),
             }),
-            _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
+
+            types::ConnectorAuthType::HeaderKey { .. }
+            | types::ConnectorAuthType::SignatureKey { .. }
+            | types::ConnectorAuthType::MultiAuthKey { .. }
+            | types::ConnectorAuthType::CurrencyAuthKey { .. }
+            | types::ConnectorAuthType::NoKey { .. } => {
+                Err(errors::ConnectorError::FailedToObtainAuthType.into())
+            }
         }
     }
 }
diff --git a/crates/router/src/connector/stax.rs b/crates/router/src/connector/stax.rs
index 82a4c7ff3233..0cfd2b89cd1a 100644
--- a/crates/router/src/connector/stax.rs
+++ b/crates/router/src/connector/stax.rs
@@ -70,6 +70,10 @@ impl ConnectorCommon for Stax {
         "stax"
     }
 
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Base
+    }
+
     fn common_get_content_type(&self) -> &'static str {
         "application/json"
     }
@@ -105,6 +109,7 @@ impl ConnectorCommon for Stax {
                     .change_context(errors::ConnectorError::ResponseDeserializationFailed)?
                     .to_owned(),
             ),
+            attempt_status: None,
         })
     }
 }
@@ -156,6 +161,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::ConnectorCustomerRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = stax::StaxCustomerRequest::try_from(req)?;
 
@@ -182,7 +188,9 @@ impl
                 .headers(types::ConnectorCustomerType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::ConnectorCustomerType::get_request_body(self, req)?)
+                .body(types::ConnectorCustomerType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -245,6 +253,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::TokenizationRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = stax::StaxTokenRequest::try_from(req)?;
 
@@ -267,7 +276,9 @@ impl
                 .url(&types::TokenizationType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::TokenizationType::get_headers(self, req, connectors)?)
-                .body(types::TokenizationType::get_request_body(self, req)?)
+                .body(types::TokenizationType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -346,8 +357,15 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let req_obj = stax::StaxPaymentsRequest::try_from(req)?;
+        let connector_router_data = stax::StaxRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+        let req_obj = stax::StaxPaymentsRequest::try_from(&connector_router_data)?;
 
         let stax_req = types::RequestBody::log_and_get_request_body(
             &req_obj,
@@ -372,7 +390,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -502,8 +522,15 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let connector_req = stax::StaxCaptureRequest::try_from(req)?;
+        let connector_router_data = stax::StaxRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount_to_capture,
+            req,
+        ))?;
+        let connector_req = stax::StaxCaptureRequest::try_from(&connector_router_data)?;
         let stax_req = types::RequestBody::log_and_get_request_body(
             &connector_req,
             utils::Encode::<stax::StaxCaptureRequest>::encode_to_string_of_json,
@@ -525,7 +552,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -656,8 +685,15 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
-        let req_obj = stax::StaxRefundRequest::try_from(req)?;
+        let connector_router_data = stax::StaxRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.refund_amount,
+            req,
+        ))?;
+        let req_obj = stax::StaxRefundRequest::try_from(&connector_router_data)?;
         let stax_req = types::RequestBody::log_and_get_request_body(
             &req_obj,
             utils::Encode::<stax::StaxRefundRequest>::encode_to_string_of_json,
@@ -678,7 +714,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/stax/transformers.rs b/crates/router/src/connector/stax/transformers.rs
index 4ee28be19375..f2aae442ddd6 100644
--- a/crates/router/src/connector/stax/transformers.rs
+++ b/crates/router/src/connector/stax/transformers.rs
@@ -11,6 +11,37 @@ use crate::{
     types::{self, api, storage::enums},
 };
 
+#[derive(Debug, Serialize)]
+pub struct StaxRouterData<T> {
+    pub amount: f64,
+    pub router_data: T,
+}
+
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for StaxRouterData<T>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        (currency_unit, currency, amount, item): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        let amount = utils::get_amount_as_f64(currency_unit, amount, currency)?;
+        Ok(Self {
+            amount,
+            router_data: item,
+        })
+    }
+}
+
 #[derive(Debug, Serialize)]
 pub struct StaxPaymentsRequestMetaData {
     tax: i64,
@@ -26,21 +57,23 @@ pub struct StaxPaymentsRequest {
     idempotency_id: Option<String>,
 }
 
-impl TryFrom<&types::PaymentsAuthorizeRouterData> for StaxPaymentsRequest {
+impl TryFrom<&StaxRouterData<&types::PaymentsAuthorizeRouterData>> for StaxPaymentsRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
-        if item.request.currency != enums::Currency::USD {
+    fn try_from(
+        item: &StaxRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
+        if item.router_data.request.currency != enums::Currency::USD {
             Err(errors::ConnectorError::NotSupported {
-                message: item.request.currency.to_string(),
+                message: item.router_data.request.currency.to_string(),
                 connector: "Stax",
             })?
         }
-        let total = utils::to_currency_base_unit_asf64(item.request.amount, item.request.currency)?;
+        let total = item.amount;
 
-        match item.request.payment_method_data.clone() {
+        match item.router_data.request.payment_method_data.clone() {
             api::PaymentMethodData::Card(_) => {
-                let pm_token = item.get_payment_method_token()?;
-                let pre_auth = !item.request.is_auto_capture()?;
+                let pm_token = item.router_data.get_payment_method_token()?;
+                let pre_auth = !item.router_data.request.is_auto_capture()?;
                 Ok(Self {
                     meta: StaxPaymentsRequestMetaData { tax: 0 },
                     total,
@@ -52,14 +85,14 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for StaxPaymentsRequest {
                             Err(errors::ConnectorError::InvalidWalletToken)?
                         }
                     }),
-                    idempotency_id: Some(item.connector_request_reference_id.clone()),
+                    idempotency_id: Some(item.router_data.connector_request_reference_id.clone()),
                 })
             }
             api::PaymentMethodData::BankDebit(
                 api_models::payments::BankDebitData::AchBankDebit { .. },
             ) => {
-                let pm_token = item.get_payment_method_token()?;
-                let pre_auth = !item.request.is_auto_capture()?;
+                let pm_token = item.router_data.get_payment_method_token()?;
+                let pre_auth = !item.router_data.request.is_auto_capture()?;
                 Ok(Self {
                     meta: StaxPaymentsRequestMetaData { tax: 0 },
                     total,
@@ -71,7 +104,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for StaxPaymentsRequest {
                             Err(errors::ConnectorError::InvalidWalletToken)?
                         }
                     }),
-                    idempotency_id: Some(item.connector_request_reference_id.clone()),
+                    idempotency_id: Some(item.router_data.connector_request_reference_id.clone()),
                 })
             }
             api::PaymentMethodData::BankDebit(_)
@@ -347,13 +380,12 @@ pub struct StaxCaptureRequest {
     total: Option<f64>,
 }
 
-impl TryFrom<&types::PaymentsCaptureRouterData> for StaxCaptureRequest {
+impl TryFrom<&StaxRouterData<&types::PaymentsCaptureRouterData>> for StaxCaptureRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsCaptureRouterData) -> Result<Self, Self::Error> {
-        let total = utils::to_currency_base_unit_asf64(
-            item.request.amount_to_capture,
-            item.request.currency,
-        )?;
+    fn try_from(
+        item: &StaxRouterData<&types::PaymentsCaptureRouterData>,
+    ) -> Result<Self, Self::Error> {
+        let total = item.amount;
         Ok(Self { total: Some(total) })
     }
 }
@@ -365,15 +397,10 @@ pub struct StaxRefundRequest {
     pub total: f64,
 }
 
-impl<F> TryFrom<&types::RefundsRouterData<F>> for StaxRefundRequest {
+impl<F> TryFrom<&StaxRouterData<&types::RefundsRouterData<F>>> for StaxRefundRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
-        Ok(Self {
-            total: utils::to_currency_base_unit_asf64(
-                item.request.refund_amount,
-                item.request.currency,
-            )?,
-        })
+    fn try_from(item: &StaxRouterData<&types::RefundsRouterData<F>>) -> Result<Self, Self::Error> {
+        Ok(Self { total: item.amount })
     }
 }
 
diff --git a/crates/router/src/connector/stripe.rs b/crates/router/src/connector/stripe.rs
index 59700ecf353a..3f1263657e83 100644
--- a/crates/router/src/connector/stripe.rs
+++ b/crates/router/src/connector/stripe.rs
@@ -144,6 +144,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsPreProcessingRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req = stripe::StripeCreditTransferSourceRequest::try_from(req)?;
         let pre_processing_request = types::RequestBody::log_and_get_request_body(
@@ -171,7 +172,7 @@ impl
                     self, req, connectors,
                 )?)
                 .body(types::PaymentsPreProcessingType::get_request_body(
-                    self, req,
+                    self, req, connectors,
                 )?)
                 .build(),
         ))
@@ -216,7 +217,16 @@ impl
                 .error
                 .code
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
-            reason: response.error.message,
+            reason: response.error.message.map(|message| {
+                response
+                    .error
+                    .decline_code
+                    .map(|decline_code| {
+                        format!("message - {}, decline_code - {}", message, decline_code)
+                    })
+                    .unwrap_or(message)
+            }),
+            attempt_status: None,
         })
     }
 }
@@ -261,6 +271,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::ConnectorCustomerRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = stripe::CustomerRequest::try_from(req)?;
         let stripe_req = types::RequestBody::log_and_get_request_body(
@@ -286,7 +297,9 @@ impl
                 .headers(types::ConnectorCustomerType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::ConnectorCustomerType::get_request_body(self, req)?)
+                .body(types::ConnectorCustomerType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -334,7 +347,16 @@ impl
                 .error
                 .code
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
-            reason: response.error.message,
+            reason: response.error.message.map(|message| {
+                response
+                    .error
+                    .decline_code
+                    .map(|decline_code| {
+                        format!("message - {}, decline_code - {}", message, decline_code)
+                    })
+                    .unwrap_or(message)
+            }),
+            attempt_status: None,
         })
     }
 }
@@ -379,6 +401,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::TokenizationRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = stripe::TokenRequest::try_from(req)?;
         let stripe_req = types::RequestBody::log_and_get_request_body(
@@ -400,7 +423,9 @@ impl
                 .url(&types::TokenizationType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::TokenizationType::get_headers(self, req, connectors)?)
-                .body(types::TokenizationType::get_request_body(self, req)?)
+                .body(types::TokenizationType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -448,7 +473,16 @@ impl
                 .error
                 .code
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
-            reason: response.error.message,
+            reason: response.error.message.map(|message| {
+                response
+                    .error
+                    .decline_code
+                    .map(|decline_code| {
+                        format!("message - {}, decline_code - {}", message, decline_code)
+                    })
+                    .unwrap_or(message)
+            }),
+            attempt_status: None,
         })
     }
 }
@@ -499,6 +533,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = stripe::CaptureRequest::try_from(req)?;
         let stripe_req = types::RequestBody::log_and_get_request_body(
@@ -522,7 +557,9 @@ impl
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -570,7 +607,16 @@ impl
                 .error
                 .code
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
-            reason: response.error.message,
+            reason: response.error.message.map(|message| {
+                response
+                    .error
+                    .decline_code
+                    .map(|decline_code| {
+                        format!("message - {}, decline_code - {}", message, decline_code)
+                    })
+                    .unwrap_or(message)
+            }),
+            attempt_status: None,
         })
     }
 }
@@ -635,7 +681,9 @@ impl
                 .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsSyncType::get_request_body(self, req)?)
+                .body(types::PaymentsSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -702,7 +750,16 @@ impl
                 .error
                 .code
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
-            reason: response.error.message,
+            reason: response.error.message.map(|message| {
+                response
+                    .error
+                    .decline_code
+                    .map(|decline_code| {
+                        format!("message - {}, decline_code - {}", message, decline_code)
+                    })
+                    .unwrap_or(message)
+            }),
+            attempt_status: None,
         })
     }
 }
@@ -765,6 +822,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         match &req.request.payment_method_data {
             api_models::payments::PaymentMethodData::BankTransfer(bank_transfer_data) => {
@@ -797,7 +855,9 @@ impl
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -848,7 +908,16 @@ impl
                 .error
                 .code
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
-            reason: response.error.message,
+            reason: response.error.message.map(|message| {
+                response
+                    .error
+                    .decline_code
+                    .map(|decline_code| {
+                        format!("message - {}, decline_code - {}", message, decline_code)
+                    })
+                    .unwrap_or(message)
+            }),
+            attempt_status: None,
         })
     }
 }
@@ -896,6 +965,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = stripe::CancelRequest::try_from(req)?;
         let stripe_req = types::RequestBody::log_and_get_request_body(
@@ -916,7 +986,9 @@ impl
             .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
             .attach_default_headers()
             .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-            .body(types::PaymentsVoidType::get_request_body(self, req)?)
+            .body(types::PaymentsVoidType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -959,7 +1031,16 @@ impl
                 .error
                 .code
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
-            reason: response.error.message,
+            reason: response.error.message.map(|message| {
+                response
+                    .error
+                    .decline_code
+                    .map(|decline_code| {
+                        format!("message - {}, decline_code - {}", message, decline_code)
+                    })
+                    .unwrap_or(message)
+            }),
+            attempt_status: None,
         })
     }
 }
@@ -1021,6 +1102,7 @@ impl
             types::SetupMandateRequestData,
             types::PaymentsResponseData,
         >,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req = stripe::SetupIntentRequest::try_from(req)?;
         let stripe_req = types::RequestBody::log_and_get_request_body(
@@ -1046,7 +1128,7 @@ impl
                 .url(&Verify::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(Verify::get_headers(self, req, connectors)?)
-                .body(Verify::get_request_body(self, req)?)
+                .body(Verify::get_request_body(self, req, connectors)?)
                 .build(),
         ))
     }
@@ -1105,7 +1187,16 @@ impl
                 .error
                 .code
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
-            reason: response.error.message,
+            reason: response.error.message.map(|message| {
+                response
+                    .error
+                    .decline_code
+                    .map(|decline_code| {
+                        format!("message - {}, decline_code - {}", message, decline_code)
+                    })
+                    .unwrap_or(message)
+            }),
+            attempt_status: None,
         })
     }
 }
@@ -1148,6 +1239,7 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = stripe::RefundRequest::try_from(req)?;
         let stripe_req = types::RequestBody::log_and_get_request_body(
@@ -1170,7 +1262,9 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -1214,7 +1308,16 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
                 .error
                 .code
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
-            reason: response.error.message,
+            reason: response.error.message.map(|message| {
+                response
+                    .error
+                    .decline_code
+                    .map(|decline_code| {
+                        format!("message - {}, decline_code - {}", message, decline_code)
+                    })
+                    .unwrap_or(message)
+            }),
+            attempt_status: None,
         })
     }
 }
@@ -1262,7 +1365,9 @@ impl services::ConnectorIntegration<api::RSync, types::RefundsData, types::Refun
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -1309,7 +1414,16 @@ impl services::ConnectorIntegration<api::RSync, types::RefundsData, types::Refun
                 .error
                 .code
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
-            reason: response.error.message,
+            reason: response.error.message.map(|message| {
+                response
+                    .error
+                    .decline_code
+                    .map(|decline_code| {
+                        format!("message - {}, decline_code - {}", message, decline_code)
+                    })
+                    .unwrap_or(message)
+            }),
+            attempt_status: None,
         })
     }
 }
@@ -1445,7 +1559,16 @@ impl
                 .error
                 .code
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
-            reason: response.error.message,
+            reason: response.error.message.map(|message| {
+                response
+                    .error
+                    .decline_code
+                    .map(|decline_code| {
+                        format!("message - {}, decline_code - {}", message, decline_code)
+                    })
+                    .unwrap_or(message)
+            }),
+            attempt_status: None,
         })
     }
 }
@@ -1539,7 +1662,16 @@ impl
                 .error
                 .code
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
-            reason: response.error.message,
+            reason: response.error.message.map(|message| {
+                response
+                    .error
+                    .decline_code
+                    .map(|decline_code| {
+                        format!("message - {}, decline_code - {}", message, decline_code)
+                    })
+                    .unwrap_or(message)
+            }),
+            attempt_status: None,
         })
     }
 }
@@ -1589,6 +1721,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::SubmitEvidenceRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let stripe_req = stripe::Evidence::try_from(req)?;
         let stripe_req_string = types::RequestBody::log_and_get_request_body(
@@ -1611,7 +1744,9 @@ impl
             .headers(types::SubmitEvidenceType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::SubmitEvidenceType::get_request_body(self, req)?)
+            .body(types::SubmitEvidenceType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -1656,7 +1791,16 @@ impl
                 .error
                 .code
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
-            reason: response.error.message,
+            reason: response.error.message.map(|message| {
+                response
+                    .error
+                    .decline_code
+                    .map(|decline_code| {
+                        format!("message - {}, decline_code - {}", message, decline_code)
+                    })
+                    .unwrap_or(message)
+            }),
+            attempt_status: None,
         })
     }
 }
diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs
index ea70977d49f6..3f0d4f543ba4 100644
--- a/crates/router/src/connector/stripe/transformers.rs
+++ b/crates/router/src/connector/stripe/transformers.rs
@@ -2122,6 +2122,7 @@ impl Deref for PaymentSyncResponse {
 pub struct LastPaymentError {
     code: String,
     message: String,
+    decline_code: Option<String>,
 }
 
 #[derive(Deserialize, Debug)]
@@ -2467,8 +2468,18 @@ impl<F, T>
                 .map(|error| types::ErrorResponse {
                     code: error.code.to_owned(),
                     message: error.code.to_owned(),
-                    reason: Some(error.message.to_owned()),
+                    reason: error
+                        .decline_code
+                        .clone()
+                        .map(|decline_code| {
+                            format!(
+                                "message - {}, decline_code - {}",
+                                error.message, decline_code
+                            )
+                        })
+                        .or(Some(error.message.clone())),
                     status_code: item.http_code,
+                    attempt_status: None,
                 });
 
         let connector_metadata =
@@ -2776,6 +2787,7 @@ pub struct ErrorDetails {
     pub error_type: Option<String>,
     pub message: Option<String>,
     pub param: Option<String>,
+    pub decline_code: Option<String>,
 }
 
 #[derive(Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
diff --git a/crates/router/src/connector/trustpay.rs b/crates/router/src/connector/trustpay.rs
index 912f1575e1e0..7509131afeef 100644
--- a/crates/router/src/connector/trustpay.rs
+++ b/crates/router/src/connector/trustpay.rs
@@ -138,6 +138,7 @@ impl ConnectorCommon for Trustpay {
                         .map(|error_code_message| error_code_message.error_code)
                         .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
                     reason: reason.or(response_data.description),
+                    attempt_status: None,
                 })
             }
             Err(error_msg) => {
@@ -235,6 +236,7 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
     fn get_request_body(
         &self,
         req: &types::RefreshTokenRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = trustpay::TrustpayAuthUpdateRequest::try_from(req)?;
         let trustpay_req = types::RequestBody::log_and_get_request_body(
@@ -256,7 +258,9 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
                 .attach_default_headers()
                 .headers(types::RefreshTokenType::get_headers(self, req, connectors)?)
                 .url(&types::RefreshTokenType::get_url(self, req, connectors)?)
-                .body(types::RefreshTokenType::get_request_body(self, req)?)
+                .body(types::RefreshTokenType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         );
         Ok(req)
@@ -293,6 +297,7 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
             // message vary for the same code, so relying on code alone as it is unique
             message: response.result_info.result_code.to_string(),
             reason: response.result_info.additional_info,
+            attempt_status: None,
         })
     }
 }
@@ -366,6 +371,7 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
             // message vary for the same code, so relying on code alone as it is unique
             message: response.status.to_string(),
             reason: Some(response.payment_description),
+            attempt_status: None,
         })
     }
 
@@ -433,6 +439,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PaymentsPreProcessingRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let currency = req.request.get_currency()?;
         let amount = req
@@ -473,7 +480,7 @@ impl
                     self, req, connectors,
                 )?)
                 .body(types::PaymentsPreProcessingType::get_request_body(
-                    self, req,
+                    self, req, connectors,
                 )?)
                 .build(),
         );
@@ -550,6 +557,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let amount = req
             .request
@@ -596,7 +604,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -665,6 +675,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = trustpay::TrustpayRouterData::try_from((
             &self.get_currency_unit(),
@@ -703,7 +714,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/trustpay/transformers.rs b/crates/router/src/connector/trustpay/transformers.rs
index 5ca4bd1ac3d2..32b52a115df0 100644
--- a/crates/router/src/connector/trustpay/transformers.rs
+++ b/crates/router/src/connector/trustpay/transformers.rs
@@ -715,6 +715,7 @@ fn handle_cards_response(
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
             reason: msg,
             status_code,
+            attempt_status: None,
         })
     } else {
         None
@@ -776,6 +777,7 @@ fn handle_bank_redirects_error_response(
         message: response.payment_result_info.result_code.to_string(),
         reason: response.payment_result_info.additional_info,
         status_code,
+        attempt_status: None,
     });
     let payment_response_data = types::PaymentsResponseData::TransactionResponse {
         resource_id: types::ResponseId::NoResponseId,
@@ -811,6 +813,7 @@ fn handle_bank_redirects_sync_response(
             message: reason_info.reason.code,
             reason: reason_info.reason.reject_reason,
             status_code,
+            attempt_status: None,
         })
     } else {
         None
@@ -937,6 +940,7 @@ impl<F, T> TryFrom<types::ResponseRouterData<F, TrustpayAuthUpdateResponse, T, t
                     message: item.response.result_info.result_code.to_string(),
                     reason: item.response.result_info.additional_info,
                     status_code: item.http_code,
+                    attempt_status: None,
                 }),
                 ..item.data
             }),
@@ -1408,6 +1412,7 @@ fn handle_cards_refund_response(
                 .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
             reason: msg,
             status_code,
+            attempt_status: None,
         })
     } else {
         None
@@ -1446,6 +1451,7 @@ fn handle_bank_redirects_refund_response(
             message: response.result_info.result_code.to_string(),
             reason: msg.map(|message| message.to_string()),
             status_code,
+            attempt_status: None,
         })
     } else {
         None
@@ -1473,6 +1479,7 @@ fn handle_bank_redirects_refund_sync_response(
             message: reason_info.reason.code,
             reason: reason_info.reason.reject_reason,
             status_code,
+            attempt_status: None,
         })
     } else {
         None
@@ -1494,6 +1501,7 @@ fn handle_bank_redirects_refund_sync_error_response(
         message: response.payment_result_info.result_code.to_string(),
         reason: response.payment_result_info.additional_info,
         status_code,
+        attempt_status: None,
     });
     //unreachable case as we are sending error as Some()
     let refund_response_data = types::RefundsResponseData {
diff --git a/crates/router/src/connector/tsys.rs b/crates/router/src/connector/tsys.rs
index 869aa5356364..71cef4be2afd 100644
--- a/crates/router/src/connector/tsys.rs
+++ b/crates/router/src/connector/tsys.rs
@@ -143,6 +143,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = tsys::TsysPaymentsRequest::try_from(req)?;
         let tsys_req = types::RequestBody::log_and_get_request_body(
@@ -168,7 +169,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -226,6 +229,7 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
     fn get_request_body(
         &self,
         req: &types::PaymentsSyncRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = tsys::TsysSyncRequest::try_from(req)?;
         let tsys_req = types::RequestBody::log_and_get_request_body(
@@ -247,7 +251,9 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
                 .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsSyncType::get_request_body(self, req)?)
+                .body(types::PaymentsSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -305,6 +311,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = tsys::TsysPaymentsCaptureRequest::try_from(req)?;
         let tsys_req = types::RequestBody::log_and_get_request_body(
@@ -328,7 +335,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -385,6 +394,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
     fn get_request_body(
         &self,
         req: &types::PaymentsCancelRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = tsys::TsysPaymentsCancelRequest::try_from(req)?;
         let tsys_req = types::RequestBody::log_and_get_request_body(
@@ -404,7 +414,9 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
             .method(services::Method::Post)
             .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
             .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
-            .body(types::PaymentsVoidType::get_request_body(self, req)?)
+            .body(types::PaymentsVoidType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
 
         Ok(Some(request))
@@ -460,6 +472,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = tsys::TsysRefundRequest::try_from(req)?;
         let tsys_req = types::RequestBody::log_and_get_request_body(
@@ -482,7 +495,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -538,6 +553,7 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
     fn get_request_body(
         &self,
         req: &types::RefundSyncRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let req_obj = tsys::TsysSyncRequest::try_from(req)?;
         let tsys_req = types::RequestBody::log_and_get_request_body(
@@ -559,7 +575,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/tsys/transformers.rs b/crates/router/src/connector/tsys/transformers.rs
index 83134568c05d..8110b9332eed 100644
--- a/crates/router/src/connector/tsys/transformers.rs
+++ b/crates/router/src/connector/tsys/transformers.rs
@@ -3,7 +3,7 @@ use masking::Secret;
 use serde::{Deserialize, Serialize};
 
 use crate::{
-    connector::utils::{CardData, PaymentsAuthorizeRequestData, RefundsRequestData},
+    connector::utils::{self, CardData, PaymentsAuthorizeRequestData, RefundsRequestData},
     core::errors,
     types::{
         self, api,
@@ -66,7 +66,20 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for TsysPaymentsRequest {
                     Ok(Self::Auth(auth_data))
                 }
             }
-            _ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()),
+            api::PaymentMethodData::CardRedirect(_)
+            | api::PaymentMethodData::Wallet(_)
+            | api::PaymentMethodData::PayLater(_)
+            | api::PaymentMethodData::BankRedirect(_)
+            | api::PaymentMethodData::BankDebit(_)
+            | api::PaymentMethodData::BankTransfer(_)
+            | api::PaymentMethodData::Crypto(_)
+            | api::PaymentMethodData::MandatePayment
+            | api::PaymentMethodData::Reward
+            | api::PaymentMethodData::Upi(_)
+            | api::PaymentMethodData::Voucher(_)
+            | api::PaymentMethodData::GiftCard(_) => Err(errors::ConnectorError::NotImplemented(
+                utils::get_unimplemented_payment_method_error_message("tsys"),
+            ))?,
         }
     }
 }
@@ -189,6 +202,7 @@ fn get_error_response(
         message: connector_error_response.response_message.clone(),
         reason: Some(connector_error_response.response_message),
         status_code,
+        attempt_status: None,
     }
 }
 
diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs
index 3a8cae3a631e..8600fe802195 100644
--- a/crates/router/src/connector/utils.rs
+++ b/crates/router/src/connector/utils.rs
@@ -292,6 +292,18 @@ pub trait PaymentsAuthorizeRequestData {
     fn get_ip_address_as_optional(&self) -> Option<Secret<String, IpAddress>>;
 }
 
+pub trait PaymentMethodTokenizationRequestData {
+    fn get_browser_info(&self) -> Result<types::BrowserInformation, Error>;
+}
+
+impl PaymentMethodTokenizationRequestData for types::PaymentMethodTokenizationData {
+    fn get_browser_info(&self) -> Result<types::BrowserInformation, Error> {
+        self.browser_info
+            .clone()
+            .ok_or_else(missing_field_err("browser_info"))
+    }
+}
+
 impl PaymentsAuthorizeRequestData for types::PaymentsAuthorizeData {
     fn is_auto_capture(&self) -> Result<bool, Error> {
         match self.capture_method {
diff --git a/crates/router/src/connector/volt.rs b/crates/router/src/connector/volt.rs
index 92d2955a0e0d..3697b8c8923f 100644
--- a/crates/router/src/connector/volt.rs
+++ b/crates/router/src/connector/volt.rs
@@ -3,7 +3,7 @@ pub mod transformers;
 use std::fmt::Debug;
 
 use error_stack::{IntoReport, ResultExt};
-use masking::ExposeInterface;
+use masking::{ExposeInterface, PeekInterface};
 use transformers as volt;
 
 use crate::{
@@ -64,8 +64,15 @@ where
                 .to_string()
                 .into(),
         )];
-        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
-        header.append(&mut api_key);
+        let access_token = req
+            .access_token
+            .clone()
+            .ok_or(errors::ConnectorError::FailedToObtainAuthType)?;
+        let auth_header = (
+            headers::AUTHORIZATION.to_string(),
+            format!("Bearer {}", access_token.token.peek()).into_masked(),
+        );
+        header.push(auth_header);
         Ok(header)
     }
 }
@@ -95,7 +102,7 @@ impl ConnectorCommon for Volt {
             .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
         Ok(vec![(
             headers::AUTHORIZATION.to_string(),
-            auth.api_key.expose().into_masked(),
+            auth.username.expose().into_masked(),
         )])
     }
 
@@ -108,11 +115,21 @@ impl ConnectorCommon for Volt {
             .parse_struct("VoltErrorResponse")
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
 
+        let reason = match &response.exception.error_list {
+            Some(error_list) => error_list
+                .iter()
+                .map(|error| error.message.clone())
+                .collect::<Vec<String>>()
+                .join(" & "),
+            None => response.exception.message.clone(),
+        };
+
         Ok(ErrorResponse {
             status_code: res.status_code,
-            code: response.code,
-            message: response.message,
-            reason: response.reason,
+            code: response.exception.message.to_string(),
+            message: response.exception.message.clone(),
+            reason: Some(reason),
+            attempt_status: None,
         })
     }
 }
@@ -130,6 +147,87 @@ impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::Payme
 impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, types::AccessToken>
     for Volt
 {
+    fn get_url(
+        &self,
+        _req: &types::RefreshTokenRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        Ok(format!("{}oauth", self.base_url(connectors)))
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        "application/x-www-form-urlencoded"
+    }
+    fn get_headers(
+        &self,
+        _req: &types::RefreshTokenRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        Ok(vec![(
+            headers::CONTENT_TYPE.to_string(),
+            types::RefreshTokenType::get_content_type(self)
+                .to_string()
+                .into(),
+        )])
+    }
+
+    fn get_request_body(
+        &self,
+        req: &types::RefreshTokenRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
+        let req_obj = volt::VoltAuthUpdateRequest::try_from(req)?;
+        let volt_req = types::RequestBody::log_and_get_request_body(
+            &req_obj,
+            utils::Encode::<volt::VoltAuthUpdateRequest>::url_encode,
+        )
+        .change_context(errors::ConnectorError::RequestEncodingFailed)?;
+
+        Ok(Some(volt_req))
+    }
+
+    fn build_request(
+        &self,
+        req: &types::RefreshTokenRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        let req = Some(
+            services::RequestBuilder::new()
+                .method(services::Method::Post)
+                .attach_default_headers()
+                .headers(types::RefreshTokenType::get_headers(self, req, connectors)?)
+                .url(&types::RefreshTokenType::get_url(self, req, connectors)?)
+                .body(types::RefreshTokenType::get_request_body(
+                    self, req, connectors,
+                )?)
+                .build(),
+        );
+        Ok(req)
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::RefreshTokenRouterData,
+        res: Response,
+    ) -> CustomResult<types::RefreshTokenRouterData, errors::ConnectorError> {
+        let response: volt::VoltAuthUpdateResponse = res
+            .response
+            .parse_struct("Volt VoltAuthUpdateResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+
+    fn get_error_response(
+        &self,
+        res: Response,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res)
+    }
 }
 
 impl
@@ -159,14 +257,15 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_url(
         &self,
         _req: &types::PaymentsAuthorizeRouterData,
-        _connectors: &settings::Connectors,
+        connectors: &settings::Connectors,
     ) -> CustomResult<String, errors::ConnectorError> {
-        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
+        Ok(format!("{}v2/payments", self.base_url(connectors)))
     }
 
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = volt::VoltRouterData::try_from((
             &self.get_currency_unit(),
@@ -198,7 +297,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -244,10 +345,18 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
 
     fn get_url(
         &self,
-        _req: &types::PaymentsSyncRouterData,
-        _connectors: &settings::Connectors,
+        req: &types::PaymentsSyncRouterData,
+        connectors: &settings::Connectors,
     ) -> CustomResult<String, errors::ConnectorError> {
-        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
+        let connector_payment_id = req
+            .request
+            .connector_transaction_id
+            .get_connector_transaction_id()
+            .change_context(errors::ConnectorError::MissingConnectorTransactionID)?;
+        Ok(format!(
+            "{}payments/{connector_payment_id}",
+            self.base_url(connectors)
+        ))
     }
 
     fn build_request(
@@ -270,7 +379,7 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
         data: &types::PaymentsSyncRouterData,
         res: Response,
     ) -> CustomResult<types::PaymentsSyncRouterData, errors::ConnectorError> {
-        let response: volt::VoltPaymentsResponse = res
+        let response: volt::VoltPsyncResponse = res
             .response
             .parse_struct("volt PaymentsSyncResponse")
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
@@ -315,6 +424,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     fn get_request_body(
         &self,
         _req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into())
     }
@@ -332,7 +442,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -381,15 +493,20 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
 
     fn get_url(
         &self,
-        _req: &types::RefundsRouterData<api::Execute>,
-        _connectors: &settings::Connectors,
+        req: &types::RefundsRouterData<api::Execute>,
+        connectors: &settings::Connectors,
     ) -> CustomResult<String, errors::ConnectorError> {
-        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
+        let connector_payment_id = req.request.connector_transaction_id.clone();
+        Ok(format!(
+            "{}payments/{connector_payment_id}/request-refund",
+            self.base_url(connectors),
+        ))
     }
 
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = volt::VoltRouterData::try_from((
             &self.get_currency_unit(),
@@ -418,7 +535,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -448,64 +567,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
 }
 
 impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponseData> for Volt {
-    fn get_headers(
-        &self,
-        req: &types::RefundSyncRouterData,
-        connectors: &settings::Connectors,
-    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
-        self.build_headers(req, connectors)
-    }
-
-    fn get_content_type(&self) -> &'static str {
-        self.common_get_content_type()
-    }
-
-    fn get_url(
-        &self,
-        _req: &types::RefundSyncRouterData,
-        _connectors: &settings::Connectors,
-    ) -> CustomResult<String, errors::ConnectorError> {
-        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
-    }
-
-    fn build_request(
-        &self,
-        req: &types::RefundSyncRouterData,
-        connectors: &settings::Connectors,
-    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
-        Ok(Some(
-            services::RequestBuilder::new()
-                .method(services::Method::Get)
-                .url(&types::RefundSyncType::get_url(self, req, connectors)?)
-                .attach_default_headers()
-                .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
-                .build(),
-        ))
-    }
-
-    fn handle_response(
-        &self,
-        data: &types::RefundSyncRouterData,
-        res: Response,
-    ) -> CustomResult<types::RefundSyncRouterData, errors::ConnectorError> {
-        let response: volt::RefundResponse =
-            res.response
-                .parse_struct("volt RefundSyncResponse")
-                .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
-        types::RouterData::try_from(types::ResponseRouterData {
-            response,
-            data: data.clone(),
-            http_code: res.status_code,
-        })
-    }
-
-    fn get_error_response(
-        &self,
-        res: Response,
-    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
-        self.build_error_response(res)
-    }
+    //Volt does not support Refund Sync
 }
 
 #[async_trait::async_trait]
diff --git a/crates/router/src/connector/volt/transformers.rs b/crates/router/src/connector/volt/transformers.rs
index 1bbbe5ff1eb4..e603ef2db06c 100644
--- a/crates/router/src/connector/volt/transformers.rs
+++ b/crates/router/src/connector/volt/transformers.rs
@@ -1,12 +1,17 @@
+use common_utils::pii::Email;
+use diesel_models::enums;
 use masking::Secret;
 use serde::{Deserialize, Serialize};
 
 use crate::{
-    connector::utils::PaymentsAuthorizeRequestData,
+    connector::utils::{self, AddressDetailsData, RouterData},
     core::errors,
-    types::{self, api, storage::enums},
+    services,
+    types::{self, api, storage::enums as storage_enums},
 };
 
+const PASSWORD: &str = "password";
+
 pub struct VoltRouterData<T> {
     pub amount: i64, // The type of amount that a connector accepts, for example, String, i64, f64, etc.
     pub router_data: T,
@@ -29,7 +34,6 @@ impl<T>
             T,
         ),
     ) -> Result<Self, Self::Error> {
-        //Todo :  use utils to convert the amount to the type of amount that a connector accepts
         Ok(Self {
             amount,
             router_data: item,
@@ -37,20 +41,38 @@ impl<T>
     }
 }
 
-#[derive(Default, Debug, Serialize, Eq, PartialEq)]
+#[derive(Debug, Serialize)]
+#[serde(rename_all = "camelCase")]
 pub struct VoltPaymentsRequest {
     amount: i64,
-    card: VoltCard,
+    currency_code: storage_enums::Currency,
+    #[serde(rename = "type")]
+    transaction_type: TransactionType,
+    merchant_internal_reference: String,
+    shopper: ShopperDetails,
+    notification_url: Option<String>,
+    payment_success_url: Option<String>,
+    payment_failure_url: Option<String>,
+    payment_pending_url: Option<String>,
+    payment_cancel_url: Option<String>,
+}
+
+#[derive(Debug, Serialize)]
+#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
+pub enum TransactionType {
+    Bills,
+    Goods,
+    PersonToPerson,
+    Other,
+    Services,
 }
 
-#[derive(Default, Debug, Serialize, Eq, PartialEq)]
-pub struct VoltCard {
-    name: Secret<String>,
-    number: cards::CardNumber,
-    expiry_month: Secret<String>,
-    expiry_year: Secret<String>,
-    cvc: Secret<String>,
-    complete: bool,
+#[derive(Debug, Serialize)]
+pub struct ShopperDetails {
+    reference: String,
+    email: Option<Email>,
+    first_name: Secret<String>,
+    last_name: Secret<String>,
 }
 
 impl TryFrom<&VoltRouterData<&types::PaymentsAuthorizeRouterData>> for VoltPaymentsRequest {
@@ -59,63 +81,184 @@ impl TryFrom<&VoltRouterData<&types::PaymentsAuthorizeRouterData>> for VoltPayme
         item: &VoltRouterData<&types::PaymentsAuthorizeRouterData>,
     ) -> Result<Self, Self::Error> {
         match item.router_data.request.payment_method_data.clone() {
-            api::PaymentMethodData::Card(req_card) => {
-                let card = VoltCard {
-                    name: req_card.card_holder_name,
-                    number: req_card.card_number,
-                    expiry_month: req_card.card_exp_month,
-                    expiry_year: req_card.card_exp_year,
-                    cvc: req_card.card_cvc,
-                    complete: item.router_data.request.is_auto_capture()?,
-                };
-                Ok(Self {
-                    amount: item.amount.to_owned(),
-                    card,
-                })
+            api::PaymentMethodData::BankRedirect(ref bank_redirect) => match bank_redirect {
+                api_models::payments::BankRedirectData::OpenBankingUk { .. } => {
+                    let amount = item.amount;
+                    let currency_code = item.router_data.request.currency;
+                    let merchant_internal_reference =
+                        item.router_data.connector_request_reference_id.clone();
+                    let payment_success_url = item.router_data.request.router_return_url.clone();
+                    let payment_failure_url = item.router_data.request.router_return_url.clone();
+                    let payment_pending_url = item.router_data.request.router_return_url.clone();
+                    let payment_cancel_url = item.router_data.request.router_return_url.clone();
+                    let notification_url = item.router_data.request.webhook_url.clone();
+                    let address = item.router_data.get_billing_address()?;
+                    let shopper = ShopperDetails {
+                        email: item.router_data.request.email.clone(),
+                        first_name: address.get_first_name()?.to_owned(),
+                        last_name: address.get_last_name()?.to_owned(),
+                        reference: item.router_data.get_customer_id()?.to_owned(),
+                    };
+                    let transaction_type = TransactionType::Services; //transaction_type is a form of enum, it is pre defined and value for this can not be taken from user so we are keeping it as Services as this transaction is type of service.
+
+                    Ok(Self {
+                        amount,
+                        currency_code,
+                        merchant_internal_reference,
+                        payment_success_url,
+                        payment_failure_url,
+                        payment_pending_url,
+                        payment_cancel_url,
+                        notification_url,
+                        shopper,
+                        transaction_type,
+                    })
+                }
+                api_models::payments::BankRedirectData::BancontactCard { .. }
+                | api_models::payments::BankRedirectData::Bizum {}
+                | api_models::payments::BankRedirectData::Blik { .. }
+                | api_models::payments::BankRedirectData::Eps { .. }
+                | api_models::payments::BankRedirectData::Giropay { .. }
+                | api_models::payments::BankRedirectData::Ideal { .. }
+                | api_models::payments::BankRedirectData::Interac { .. }
+                | api_models::payments::BankRedirectData::OnlineBankingCzechRepublic { .. }
+                | api_models::payments::BankRedirectData::OnlineBankingFinland { .. }
+                | api_models::payments::BankRedirectData::OnlineBankingPoland { .. }
+                | api_models::payments::BankRedirectData::OnlineBankingSlovakia { .. }
+                | api_models::payments::BankRedirectData::Przelewy24 { .. }
+                | api_models::payments::BankRedirectData::Sofort { .. }
+                | api_models::payments::BankRedirectData::Trustly { .. }
+                | api_models::payments::BankRedirectData::OnlineBankingFpx { .. }
+                | api_models::payments::BankRedirectData::OnlineBankingThailand { .. } => {
+                    Err(errors::ConnectorError::NotSupported {
+                        message: utils::SELECTED_PAYMENT_METHOD.to_string(),
+                        connector: "Volt",
+                    }
+                    .into())
+                }
+            },
+            api_models::payments::PaymentMethodData::Card(_)
+            | api_models::payments::PaymentMethodData::CardRedirect(_)
+            | api_models::payments::PaymentMethodData::Wallet(_)
+            | api_models::payments::PaymentMethodData::PayLater(_)
+            | api_models::payments::PaymentMethodData::BankDebit(_)
+            | api_models::payments::PaymentMethodData::BankTransfer(_)
+            | api_models::payments::PaymentMethodData::Crypto(_)
+            | api_models::payments::PaymentMethodData::MandatePayment
+            | api_models::payments::PaymentMethodData::Reward
+            | api_models::payments::PaymentMethodData::Upi(_)
+            | api_models::payments::PaymentMethodData::Voucher(_)
+            | api_models::payments::PaymentMethodData::GiftCard(_) => {
+                Err(errors::ConnectorError::NotSupported {
+                    message: utils::SELECTED_PAYMENT_METHOD.to_string(),
+                    connector: "Volt",
+                }
+                .into())
             }
-            _ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()),
         }
     }
 }
 
+#[derive(Debug, Clone, Serialize, PartialEq)]
+pub struct VoltAuthUpdateRequest {
+    grant_type: String,
+    client_id: Secret<String>,
+    client_secret: Secret<String>,
+    username: Secret<String>,
+    password: Secret<String>,
+}
+
+impl TryFrom<&types::RefreshTokenRouterData> for VoltAuthUpdateRequest {
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(item: &types::RefreshTokenRouterData) -> Result<Self, Self::Error> {
+        let auth = VoltAuthType::try_from(&item.connector_auth_type)?;
+        Ok(Self {
+            grant_type: PASSWORD.to_string(),
+            username: auth.username,
+            password: auth.password,
+            client_id: auth.client_id,
+            client_secret: auth.client_secret,
+        })
+    }
+}
+
+#[derive(Debug, Clone, Deserialize)]
+pub struct VoltAuthUpdateResponse {
+    pub access_token: Secret<String>,
+    pub token_type: String,
+    pub expires_in: i64,
+    pub refresh_token: String,
+}
+
+impl<F, T> TryFrom<types::ResponseRouterData<F, VoltAuthUpdateResponse, T, types::AccessToken>>
+    for types::RouterData<F, T, types::AccessToken>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: types::ResponseRouterData<F, VoltAuthUpdateResponse, T, types::AccessToken>,
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            response: Ok(types::AccessToken {
+                token: item.response.access_token,
+                expires: item.response.expires_in,
+            }),
+            ..item.data
+        })
+    }
+}
+
 pub struct VoltAuthType {
-    pub(super) api_key: Secret<String>,
+    pub(super) username: Secret<String>,
+    pub(super) password: Secret<String>,
+    pub(super) client_id: Secret<String>,
+    pub(super) client_secret: Secret<String>,
 }
 
 impl TryFrom<&types::ConnectorAuthType> for VoltAuthType {
     type Error = error_stack::Report<errors::ConnectorError>;
     fn try_from(auth_type: &types::ConnectorAuthType) -> Result<Self, Self::Error> {
         match auth_type {
-            types::ConnectorAuthType::HeaderKey { api_key } => Ok(Self {
-                api_key: api_key.to_owned(),
+            types::ConnectorAuthType::MultiAuthKey {
+                api_key,
+                key1,
+                api_secret,
+                key2,
+            } => Ok(Self {
+                username: api_key.to_owned(),
+                password: api_secret.to_owned(),
+                client_id: key1.to_owned(),
+                client_secret: key2.to_owned(),
             }),
             _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
         }
     }
 }
 
-#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
-#[serde(rename_all = "lowercase")]
-pub enum VoltPaymentStatus {
-    Succeeded,
-    Failed,
-    #[default]
-    Processing,
-}
-
 impl From<VoltPaymentStatus> for enums::AttemptStatus {
     fn from(item: VoltPaymentStatus) -> Self {
         match item {
-            VoltPaymentStatus::Succeeded => Self::Charged,
-            VoltPaymentStatus::Failed => Self::Failure,
-            VoltPaymentStatus::Processing => Self::Authorizing,
+            VoltPaymentStatus::Completed
+            | VoltPaymentStatus::Received
+            | VoltPaymentStatus::Settled => Self::Charged,
+            VoltPaymentStatus::DelayedAtBank => Self::Pending,
+            VoltPaymentStatus::NewPayment
+            | VoltPaymentStatus::BankRedirect
+            | VoltPaymentStatus::AwaitingCheckoutAuthorisation => Self::AuthenticationPending,
+            VoltPaymentStatus::RefusedByBank
+            | VoltPaymentStatus::RefusedByRisk
+            | VoltPaymentStatus::NotReceived
+            | VoltPaymentStatus::ErrorAtBank
+            | VoltPaymentStatus::CancelledByUser
+            | VoltPaymentStatus::AbandonedByUser
+            | VoltPaymentStatus::Failed => Self::Failure,
         }
     }
 }
 
-#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
 pub struct VoltPaymentsResponse {
-    status: VoltPaymentStatus,
+    checkout_url: String,
     id: String,
 }
 
@@ -126,16 +269,73 @@ impl<F, T>
     type Error = error_stack::Report<errors::ConnectorError>;
     fn try_from(
         item: types::ResponseRouterData<F, VoltPaymentsResponse, T, types::PaymentsResponseData>,
+    ) -> Result<Self, Self::Error> {
+        let url = item.response.checkout_url;
+        let redirection_data = Some(services::RedirectForm::Form {
+            endpoint: url,
+            method: services::Method::Get,
+            form_fields: Default::default(),
+        });
+        Ok(Self {
+            status: enums::AttemptStatus::AuthenticationPending,
+            response: Ok(types::PaymentsResponseData::TransactionResponse {
+                resource_id: types::ResponseId::ConnectorTransactionId(item.response.id.clone()),
+                redirection_data,
+                mandate_reference: None,
+                connector_metadata: None,
+                network_txn_id: None,
+                connector_response_reference_id: Some(item.response.id),
+            }),
+            ..item.data
+        })
+    }
+}
+
+#[derive(Debug, Deserialize)]
+#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
+pub enum VoltPaymentStatus {
+    NewPayment,
+    Completed,
+    Received,
+    NotReceived,
+    BankRedirect,
+    DelayedAtBank,
+    AwaitingCheckoutAuthorisation,
+    RefusedByBank,
+    RefusedByRisk,
+    ErrorAtBank,
+    CancelledByUser,
+    AbandonedByUser,
+    Failed,
+    Settled,
+}
+#[derive(Debug, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct VoltPsyncResponse {
+    status: VoltPaymentStatus,
+    id: String,
+    merchant_internal_reference: Option<String>,
+}
+
+impl<F, T> TryFrom<types::ResponseRouterData<F, VoltPsyncResponse, T, types::PaymentsResponseData>>
+    for types::RouterData<F, T, types::PaymentsResponseData>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: types::ResponseRouterData<F, VoltPsyncResponse, T, types::PaymentsResponseData>,
     ) -> Result<Self, Self::Error> {
         Ok(Self {
             status: enums::AttemptStatus::from(item.response.status),
             response: Ok(types::PaymentsResponseData::TransactionResponse {
-                resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
+                resource_id: types::ResponseId::ConnectorTransactionId(item.response.id.clone()),
                 redirection_data: None,
                 mandate_reference: None,
                 connector_metadata: None,
                 network_txn_id: None,
-                connector_response_reference_id: None,
+                connector_response_reference_id: item
+                    .response
+                    .merchant_internal_reference
+                    .or(Some(item.response.id)),
             }),
             ..item.data
         })
@@ -147,13 +347,15 @@ impl<F, T>
 #[derive(Default, Debug, Serialize)]
 pub struct VoltRefundRequest {
     pub amount: i64,
+    pub external_reference: String,
 }
 
 impl<F> TryFrom<&VoltRouterData<&types::RefundsRouterData<F>>> for VoltRefundRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
     fn try_from(item: &VoltRouterData<&types::RefundsRouterData<F>>) -> Result<Self, Self::Error> {
         Ok(Self {
-            amount: item.amount.to_owned(),
+            amount: item.router_data.request.refund_amount,
+            external_reference: item.router_data.request.refund_id.clone(),
         })
     }
 }
@@ -180,10 +382,9 @@ impl From<RefundStatus> for enums::RefundStatus {
     }
 }
 
-#[derive(Default, Debug, Clone, Serialize, Deserialize)]
+#[derive(Default, Debug, Clone, Deserialize)]
 pub struct RefundResponse {
     id: String,
-    status: RefundStatus,
 }
 
 impl TryFrom<types::RefundsResponseRouterData<api::Execute, RefundResponse>>
@@ -196,34 +397,28 @@ impl TryFrom<types::RefundsResponseRouterData<api::Execute, RefundResponse>>
         Ok(Self {
             response: Ok(types::RefundsResponseData {
                 connector_refund_id: item.response.id.to_string(),
-                refund_status: enums::RefundStatus::from(item.response.status),
+                refund_status: enums::RefundStatus::Pending, //We get Refund Status only by Webhooks
             }),
             ..item.data
         })
     }
 }
 
-impl TryFrom<types::RefundsResponseRouterData<api::RSync, RefundResponse>>
-    for types::RefundsRouterData<api::RSync>
-{
-    type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(
-        item: types::RefundsResponseRouterData<api::RSync, RefundResponse>,
-    ) -> Result<Self, Self::Error> {
-        Ok(Self {
-            response: Ok(types::RefundsResponseData {
-                connector_refund_id: item.response.id.to_string(),
-                refund_status: enums::RefundStatus::from(item.response.status),
-            }),
-            ..item.data
-        })
-    }
+#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
+pub struct VoltErrorResponse {
+    pub exception: VoltErrorException,
 }
 
 #[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
-pub struct VoltErrorResponse {
-    pub status_code: u16,
-    pub code: String,
+#[serde(rename_all = "camelCase")]
+pub struct VoltErrorException {
+    pub code: u64,
+    pub message: String,
+    pub error_list: Option<Vec<VoltErrorList>>,
+}
+
+#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
+pub struct VoltErrorList {
+    pub property: String,
     pub message: String,
-    pub reason: Option<String>,
 }
diff --git a/crates/router/src/connector/wise.rs b/crates/router/src/connector/wise.rs
index 9616533a4554..5eba54eab4f7 100644
--- a/crates/router/src/connector/wise.rs
+++ b/crates/router/src/connector/wise.rs
@@ -94,6 +94,7 @@ impl ConnectorCommon for Wise {
                         code: e.code.clone(),
                         message: e.message.clone(),
                         reason: None,
+                        attempt_status: None,
                     })
                 } else {
                     Ok(types::ErrorResponse {
@@ -101,6 +102,7 @@ impl ConnectorCommon for Wise {
                         code: default_status,
                         message: response.message.unwrap_or_default(),
                         reason: None,
+                        attempt_status: None,
                     })
                 }
             }
@@ -109,6 +111,7 @@ impl ConnectorCommon for Wise {
                 code: default_status,
                 message: response.message.unwrap_or_default(),
                 reason: None,
+                attempt_status: None,
             }),
         }
     }
@@ -289,6 +292,7 @@ impl services::ConnectorIntegration<api::PoCancel, types::PayoutsData, types::Pa
             code,
             message,
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -322,6 +326,7 @@ impl services::ConnectorIntegration<api::PoQuote, types::PayoutsData, types::Pay
     fn get_request_body(
         &self,
         req: &types::PayoutsRouterData<api::PoQuote>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = wise::WisePayoutQuoteRequest::try_from(req)?;
         let wise_req = types::RequestBody::log_and_get_request_body(
@@ -342,7 +347,9 @@ impl services::ConnectorIntegration<api::PoQuote, types::PayoutsData, types::Pay
             .url(&types::PayoutQuoteType::get_url(self, req, connectors)?)
             .attach_default_headers()
             .headers(types::PayoutQuoteType::get_headers(self, req, connectors)?)
-            .body(types::PayoutQuoteType::get_request_body(self, req)?)
+            .body(types::PayoutQuoteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
 
         Ok(Some(request))
@@ -397,6 +404,7 @@ impl
     fn get_request_body(
         &self,
         req: &types::PayoutsRouterData<api::PoRecipient>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = wise::WiseRecipientCreateRequest::try_from(req)?;
         let wise_req = types::RequestBody::log_and_get_request_body(
@@ -419,7 +427,9 @@ impl
             .headers(types::PayoutRecipientType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::PayoutRecipientType::get_request_body(self, req)?)
+            .body(types::PayoutRecipientType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
 
         Ok(Some(request))
@@ -512,6 +522,7 @@ impl services::ConnectorIntegration<api::PoCreate, types::PayoutsData, types::Pa
     fn get_request_body(
         &self,
         req: &types::PayoutsRouterData<api::PoCreate>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = wise::WisePayoutCreateRequest::try_from(req)?;
         let wise_req = types::RequestBody::log_and_get_request_body(
@@ -532,7 +543,9 @@ impl services::ConnectorIntegration<api::PoCreate, types::PayoutsData, types::Pa
             .url(&types::PayoutCreateType::get_url(self, req, connectors)?)
             .attach_default_headers()
             .headers(types::PayoutCreateType::get_headers(self, req, connectors)?)
-            .body(types::PayoutCreateType::get_request_body(self, req)?)
+            .body(types::PayoutCreateType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
 
         Ok(Some(request))
@@ -608,6 +621,7 @@ impl services::ConnectorIntegration<api::PoFulfill, types::PayoutsData, types::P
     fn get_request_body(
         &self,
         req: &types::PayoutsRouterData<api::PoFulfill>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = wise::WisePayoutFulfillRequest::try_from(req)?;
         let wise_req = types::RequestBody::log_and_get_request_body(
@@ -630,7 +644,9 @@ impl services::ConnectorIntegration<api::PoFulfill, types::PayoutsData, types::P
             .headers(types::PayoutFulfillType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::PayoutFulfillType::get_request_body(self, req)?)
+            .body(types::PayoutFulfillType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
 
         Ok(Some(request))
diff --git a/crates/router/src/connector/worldline.rs b/crates/router/src/connector/worldline.rs
index b10e3dcd74c8..7fcca08d8bfe 100644
--- a/crates/router/src/connector/worldline.rs
+++ b/crates/router/src/connector/worldline.rs
@@ -378,6 +378,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
             types::PaymentsCaptureData,
             types::PaymentsResponseData,
         >,
+        _connectors: &Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = worldline::ApproveRequest::try_from(req)?;
 
@@ -406,7 +407,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
                 .headers(types::PaymentsCaptureType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -489,6 +492,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = worldline::WorldlineRouterData::try_from((
             &self.get_currency_unit(),
@@ -524,7 +528,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -588,6 +594,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_req = worldline::WorldlineRefundRequest::try_from(req)?;
         let refund_req = types::RequestBody::log_and_get_request_body(
@@ -610,7 +617,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
diff --git a/crates/router/src/connector/worldline/transformers.rs b/crates/router/src/connector/worldline/transformers.rs
index f11c23980809..6cb8862f69b1 100644
--- a/crates/router/src/connector/worldline/transformers.rs
+++ b/crates/router/src/connector/worldline/transformers.rs
@@ -247,11 +247,19 @@ impl
                     make_bank_redirect_request(&item.router_data.request, bank_redirect)?,
                 ))
             }
-            _ => {
-                return Err(
-                    errors::ConnectorError::NotImplemented("Payment methods".to_string()).into(),
-                )
-            }
+            api::PaymentMethodData::CardRedirect(_)
+            | api::PaymentMethodData::Wallet(_)
+            | api::PaymentMethodData::PayLater(_)
+            | api::PaymentMethodData::BankDebit(_)
+            | api::PaymentMethodData::BankTransfer(_)
+            | api::PaymentMethodData::Crypto(_)
+            | api::PaymentMethodData::MandatePayment
+            | api::PaymentMethodData::Reward
+            | api::PaymentMethodData::Upi(_)
+            | api::PaymentMethodData::Voucher(_)
+            | api::PaymentMethodData::GiftCard(_) => Err(errors::ConnectorError::NotImplemented(
+                utils::get_unimplemented_payment_method_error_message("worldline"),
+            ))?,
         };
 
         let customer =
@@ -393,10 +401,25 @@ fn make_bank_redirect_request(
             },
             809,
         ),
-        _ => {
-            return Err(
-                errors::ConnectorError::NotImplemented("Payment methods".to_string()).into(),
+        payments::BankRedirectData::BancontactCard { .. }
+        | payments::BankRedirectData::Bizum {}
+        | payments::BankRedirectData::Blik { .. }
+        | payments::BankRedirectData::Eps { .. }
+        | payments::BankRedirectData::Interac { .. }
+        | payments::BankRedirectData::OnlineBankingCzechRepublic { .. }
+        | payments::BankRedirectData::OnlineBankingFinland { .. }
+        | payments::BankRedirectData::OnlineBankingPoland { .. }
+        | payments::BankRedirectData::OnlineBankingSlovakia { .. }
+        | payments::BankRedirectData::OpenBankingUk { .. }
+        | payments::BankRedirectData::Przelewy24 { .. }
+        | payments::BankRedirectData::Sofort { .. }
+        | payments::BankRedirectData::Trustly { .. }
+        | payments::BankRedirectData::OnlineBankingFpx { .. }
+        | payments::BankRedirectData::OnlineBankingThailand { .. } => {
+            return Err(errors::ConnectorError::NotImplemented(
+                utils::get_unimplemented_payment_method_error_message("worldline"),
             )
+            .into())
         }
     };
     Ok(RedirectPaymentMethod {
@@ -565,12 +588,12 @@ impl<F, T> TryFrom<types::ResponseRouterData<F, Payment, T, PaymentsResponseData
                 item.response.capture_method,
             )),
             response: Ok(types::PaymentsResponseData::TransactionResponse {
-                resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
+                resource_id: types::ResponseId::ConnectorTransactionId(item.response.id.clone()),
                 redirection_data: None,
                 mandate_reference: None,
                 connector_metadata: None,
                 network_txn_id: None,
-                connector_response_reference_id: None,
+                connector_response_reference_id: Some(item.response.id),
             }),
             ..item.data
         })
@@ -616,12 +639,14 @@ impl<F, T> TryFrom<types::ResponseRouterData<F, PaymentResponse, T, PaymentsResp
                 item.response.payment.capture_method,
             )),
             response: Ok(types::PaymentsResponseData::TransactionResponse {
-                resource_id: types::ResponseId::ConnectorTransactionId(item.response.payment.id),
+                resource_id: types::ResponseId::ConnectorTransactionId(
+                    item.response.payment.id.clone(),
+                ),
                 redirection_data,
                 mandate_reference: None,
                 connector_metadata: None,
                 network_txn_id: None,
-                connector_response_reference_id: None,
+                connector_response_reference_id: Some(item.response.payment.id),
             }),
             ..item.data
         })
diff --git a/crates/router/src/connector/worldpay.rs b/crates/router/src/connector/worldpay.rs
index 60a5fc830453..60579fb5dd3e 100644
--- a/crates/router/src/connector/worldpay.rs
+++ b/crates/router/src/connector/worldpay.rs
@@ -94,6 +94,7 @@ impl ConnectorCommon for Worldpay {
             code: response.error_name,
             message: response.message,
             reason: response.validation_errors.map(|e| e.to_string()),
+            attempt_status: None,
         })
     }
 }
@@ -274,7 +275,9 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
                 .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
-                .body(types::PaymentsSyncType::get_request_body(self, req)?)
+                .body(types::PaymentsSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -431,6 +434,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = worldpay::WorldpayRouterData::try_from((
             &self.get_currency_unit(),
@@ -462,7 +466,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -514,6 +520,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundExecuteRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_request = WorldpayRefundRequest::try_from(req)?;
         let fiserv_refund_request = types::RequestBody::log_and_get_request_body(
@@ -549,7 +556,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -621,7 +630,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/worldpay/transformers.rs b/crates/router/src/connector/worldpay/transformers.rs
index 61d04a8e9f11..d31f4d65e78c 100644
--- a/crates/router/src/connector/worldpay/transformers.rs
+++ b/crates/router/src/connector/worldpay/transformers.rs
@@ -217,7 +217,13 @@ impl From<EventType> for enums::AttemptStatus {
             EventType::CaptureFailed => Self::CaptureFailed,
             EventType::Refused => Self::Failure,
             EventType::Charged | EventType::SentForSettlement => Self::Charged,
-            _ => Self::Pending,
+            EventType::Cancelled
+            | EventType::SentForRefund
+            | EventType::RefundFailed
+            | EventType::Refunded
+            | EventType::Error
+            | EventType::Expired
+            | EventType::Unknown => Self::Pending,
         }
     }
 }
@@ -227,7 +233,16 @@ impl From<EventType> for enums::RefundStatus {
         match value {
             EventType::Refunded => Self::Success,
             EventType::RefundFailed => Self::Failure,
-            _ => Self::Pending,
+            EventType::Authorized
+            | EventType::Cancelled
+            | EventType::Charged
+            | EventType::SentForRefund
+            | EventType::Refused
+            | EventType::Error
+            | EventType::SentForSettlement
+            | EventType::Expired
+            | EventType::CaptureFailed
+            | EventType::Unknown => Self::Pending,
         }
     }
 }
diff --git a/crates/router/src/connector/zen.rs b/crates/router/src/connector/zen.rs
index d93075c37350..bdbdf623f934 100644
--- a/crates/router/src/connector/zen.rs
+++ b/crates/router/src/connector/zen.rs
@@ -126,6 +126,7 @@ impl ConnectorCommon for Zen {
                 |error| error.message,
             ),
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -215,6 +216,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     fn get_request_body(
         &self,
         req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = zen::ZenRouterData::try_from((
             &self.get_currency_unit(),
@@ -246,7 +248,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
                 .headers(types::PaymentsAuthorizeType::get_headers(
                     self, req, connectors,
                 )?)
-                .body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
+                .body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
@@ -410,6 +414,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     fn get_request_body(
         &self,
         req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         let connector_router_data = zen::ZenRouterData::try_from((
             &self.get_currency_unit(),
@@ -438,7 +443,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
             .headers(types::RefundExecuteType::get_headers(
                 self, req, connectors,
             )?)
-            .body(types::RefundExecuteType::get_request_body(self, req)?)
+            .body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
             .build();
         Ok(Some(request))
     }
@@ -506,7 +513,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
                 .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                 .attach_default_headers()
                 .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
-                .body(types::RefundSyncType::get_request_body(self, req)?)
+                .body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
                 .build(),
         ))
     }
diff --git a/crates/router/src/connector/zen/transformers.rs b/crates/router/src/connector/zen/transformers.rs
index 4d0d3c7f1079..6b0d46dec8d1 100644
--- a/crates/router/src/connector/zen/transformers.rs
+++ b/crates/router/src/connector/zen/transformers.rs
@@ -290,10 +290,9 @@ impl
             | api_models::payments::VoucherData::FamilyMart { .. }
             | api_models::payments::VoucherData::Seicomart { .. }
             | api_models::payments::VoucherData::PayEasy { .. } => {
-                Err(errors::ConnectorError::NotSupported {
-                    message: utils::SELECTED_PAYMENT_METHOD.to_string(),
-                    connector: "Zen",
-                })?
+                Err(errors::ConnectorError::NotImplemented(
+                    utils::get_unimplemented_payment_method_error_message("Zen"),
+                ))?
             }
         };
         Ok(Self::ApiRequest(Box::new(ApiRequest {
@@ -342,12 +341,8 @@ impl
             api_models::payments::BankTransferData::Pse { .. } => {
                 ZenPaymentChannels::PclBoacompraPse
             }
-            api_models::payments::BankTransferData::SepaBankTransfer { .. } => {
-                Err(errors::ConnectorError::NotImplemented(
-                    utils::get_unimplemented_payment_method_error_message("Zen"),
-                ))?
-            }
-            api_models::payments::BankTransferData::AchBankTransfer { .. }
+            api_models::payments::BankTransferData::SepaBankTransfer { .. }
+            | api_models::payments::BankTransferData::AchBankTransfer { .. }
             | api_models::payments::BankTransferData::BacsBankTransfer { .. }
             | api_models::payments::BankTransferData::PermataBankTransfer { .. }
             | api_models::payments::BankTransferData::BcaBankTransfer { .. }
@@ -356,10 +351,9 @@ impl
             | api_models::payments::BankTransferData::CimbVaBankTransfer { .. }
             | api_models::payments::BankTransferData::DanamonVaBankTransfer { .. }
             | api_models::payments::BankTransferData::MandiriVaBankTransfer { .. } => {
-                Err(errors::ConnectorError::NotSupported {
-                    message: utils::SELECTED_PAYMENT_METHOD.to_string(),
-                    connector: "Zen",
-                })?
+                Err(errors::ConnectorError::NotImplemented(
+                    utils::get_unimplemented_payment_method_error_message("Zen"),
+                ))?
             }
         };
         Ok(Self::ApiRequest(Box::new(ApiRequest {
@@ -489,12 +483,8 @@ impl
             api_models::payments::WalletData::WeChatPayRedirect(_)
             | api_models::payments::WalletData::PaypalRedirect(_)
             | api_models::payments::WalletData::ApplePay(_)
-            | api_models::payments::WalletData::GooglePay(_) => {
-                Err(errors::ConnectorError::NotImplemented(
-                    utils::get_unimplemented_payment_method_error_message("Zen"),
-                ))?
-            }
-            api_models::payments::WalletData::AliPayQr(_)
+            | api_models::payments::WalletData::GooglePay(_)
+            | api_models::payments::WalletData::AliPayQr(_)
             | api_models::payments::WalletData::AliPayRedirect(_)
             | api_models::payments::WalletData::AliPayHkRedirect(_)
             | api_models::payments::WalletData::MomoRedirect(_)
@@ -514,10 +504,9 @@ impl
             | api_models::payments::WalletData::CashappQr(_)
             | api_models::payments::WalletData::SwishQr(_)
             | api_models::payments::WalletData::WeChatPayQr(_) => {
-                Err(errors::ConnectorError::NotSupported {
-                    message: utils::SELECTED_PAYMENT_METHOD.to_string(),
-                    connector: "Zen",
-                })?
+                Err(errors::ConnectorError::NotImplemented(
+                    utils::get_unimplemented_payment_method_error_message("Zen"),
+                ))?
             }
         };
         let terminal_uuid = session_data
@@ -719,10 +708,9 @@ impl TryFrom<&ZenRouterData<&types::PaymentsAuthorizeRouterData>> for ZenPayment
             | api_models::payments::PaymentMethodData::MandatePayment
             | api_models::payments::PaymentMethodData::Reward
             | api_models::payments::PaymentMethodData::Upi(_) => {
-                Err(errors::ConnectorError::NotSupported {
-                    message: utils::SELECTED_PAYMENT_METHOD.to_string(),
-                    connector: "Zen",
-                })?
+                Err(errors::ConnectorError::NotImplemented(
+                    utils::get_unimplemented_payment_method_error_message("Zen"),
+                ))?
             }
         }
     }
@@ -736,13 +724,8 @@ impl TryFrom<&api_models::payments::BankRedirectData> for ZenPaymentsRequest {
             | api_models::payments::BankRedirectData::Sofort { .. }
             | api_models::payments::BankRedirectData::BancontactCard { .. }
             | api_models::payments::BankRedirectData::Blik { .. }
-            | api_models::payments::BankRedirectData::Trustly { .. } => {
-                Err(errors::ConnectorError::NotImplemented(
-                    utils::get_unimplemented_payment_method_error_message("Zen"),
-                )
-                .into())
-            }
-            api_models::payments::BankRedirectData::Eps { .. }
+            | api_models::payments::BankRedirectData::Trustly { .. }
+            | api_models::payments::BankRedirectData::Eps { .. }
             | api_models::payments::BankRedirectData::Giropay { .. }
             | api_models::payments::BankRedirectData::Przelewy24 { .. }
             | api_models::payments::BankRedirectData::Bizum {}
@@ -754,10 +737,9 @@ impl TryFrom<&api_models::payments::BankRedirectData> for ZenPaymentsRequest {
             | api_models::payments::BankRedirectData::OpenBankingUk { .. }
             | api_models::payments::BankRedirectData::OnlineBankingFpx { .. }
             | api_models::payments::BankRedirectData::OnlineBankingThailand { .. } => {
-                Err(errors::ConnectorError::NotSupported {
-                    message: utils::SELECTED_PAYMENT_METHOD.to_string(),
-                    connector: "Zen",
-                }
+                Err(errors::ConnectorError::NotImplemented(
+                    utils::get_unimplemented_payment_method_error_message("Zen"),
+                )
                 .into())
             }
         }
@@ -776,10 +758,9 @@ impl TryFrom<&api_models::payments::PayLaterData> for ZenPaymentsRequest {
             | api_models::payments::PayLaterData::WalleyRedirect {}
             | api_models::payments::PayLaterData::AlmaRedirect {}
             | api_models::payments::PayLaterData::AtomeRedirect {} => {
-                Err(errors::ConnectorError::NotSupported {
-                    message: utils::SELECTED_PAYMENT_METHOD.to_string(),
-                    connector: "Zen",
-                }
+                Err(errors::ConnectorError::NotImplemented(
+                    utils::get_unimplemented_payment_method_error_message("Zen"),
+                )
                 .into())
             }
         }
@@ -794,10 +775,9 @@ impl TryFrom<&api_models::payments::BankDebitData> for ZenPaymentsRequest {
             | api_models::payments::BankDebitData::SepaBankDebit { .. }
             | api_models::payments::BankDebitData::BecsBankDebit { .. }
             | api_models::payments::BankDebitData::BacsBankDebit { .. } => {
-                Err(errors::ConnectorError::NotSupported {
-                    message: utils::SELECTED_PAYMENT_METHOD.to_string(),
-                    connector: "Zen",
-                }
+                Err(errors::ConnectorError::NotImplemented(
+                    utils::get_unimplemented_payment_method_error_message("Zen"),
+                )
                 .into())
             }
         }
@@ -810,12 +790,10 @@ impl TryFrom<&api_models::payments::CardRedirectData> for ZenPaymentsRequest {
         match value {
             api_models::payments::CardRedirectData::Knet {}
             | api_models::payments::CardRedirectData::Benefit {}
-            | api_models::payments::CardRedirectData::MomoAtm {}
-            | api_models::payments::CardRedirectData::CardRedirect {} => {
-                Err(errors::ConnectorError::NotSupported {
-                    message: utils::SELECTED_PAYMENT_METHOD.to_string(),
-                    connector: "Zen",
-                }
+            | api_models::payments::CardRedirectData::MomoAtm {} => {
+                Err(errors::ConnectorError::NotImplemented(
+                    utils::get_unimplemented_payment_method_error_message("Zen"),
+                )
                 .into())
             }
         }
@@ -826,19 +804,13 @@ impl TryFrom<&api_models::payments::GiftCardData> for ZenPaymentsRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
     fn try_from(value: &api_models::payments::GiftCardData) -> Result<Self, Self::Error> {
         match value {
-            api_models::payments::GiftCardData::PaySafeCard {} => {
+            api_models::payments::GiftCardData::PaySafeCard {}
+            | api_models::payments::GiftCardData::Givex(_) => {
                 Err(errors::ConnectorError::NotImplemented(
                     utils::get_unimplemented_payment_method_error_message("Zen"),
                 )
                 .into())
             }
-            api_models::payments::GiftCardData::Givex(_) => {
-                Err(errors::ConnectorError::NotSupported {
-                    message: utils::SELECTED_PAYMENT_METHOD.to_string(),
-                    connector: "Zen",
-                }
-                .into())
-            }
         }
     }
 }
diff --git a/crates/router/src/consts.rs b/crates/router/src/consts.rs
index 02db8b1754ed..410e3c1113b1 100644
--- a/crates/router/src/consts.rs
+++ b/crates/router/src/consts.rs
@@ -1,3 +1,6 @@
+#[cfg(feature = "olap")]
+pub mod user;
+
 // ID generation
 pub(crate) const ID_LENGTH: usize = 20;
 pub(crate) const MAX_ID_LENGTH: usize = 64;
@@ -13,6 +16,7 @@ pub(crate) const ALPHABETS: [char; 62] = [
 pub const REQUEST_TIME_OUT: u64 = 30;
 pub const REQUEST_TIMEOUT_ERROR_CODE: &str = "TIMEOUT";
 pub const REQUEST_TIMEOUT_ERROR_MESSAGE: &str = "Connector did not respond in specified time";
+pub const REQUEST_TIMEOUT_PAYMENT_NOT_FOUND: &str = "Timed out ,payment not found";
 pub const REQUEST_TIMEOUT_ERROR_MESSAGE_FROM_PSYNC: &str =
     "This Payment has been moved to failed as there is no response from the connector";
 
@@ -46,3 +50,11 @@ pub(crate) const QR_IMAGE_DATA_SOURCE_STRING: &str = "data:image/png;base64";
 pub(crate) const MERCHANT_ID_FIELD_EXTENSION_ID: &str = "1.2.840.113635.100.6.32";
 
 pub(crate) const METRICS_HOST_TAG_NAME: &str = "host";
+pub const MAX_ROUTING_CONFIGS_PER_MERCHANT: usize = 100;
+pub const ROUTING_CONFIG_ID_LENGTH: usize = 10;
+
+pub const LOCKER_REDIS_PREFIX: &str = "LOCKER_PM_TOKEN";
+pub const LOCKER_REDIS_EXPIRY_SECONDS: u32 = 60 * 15; // 15 minutes
+
+#[cfg(any(feature = "olap", feature = "oltp"))]
+pub const JWT_TOKEN_TIME_IN_SECS: u64 = 60 * 60 * 24 * 2; // 2 days
diff --git a/crates/router/src/consts/user.rs b/crates/router/src/consts/user.rs
new file mode 100644
index 000000000000..3a71fed01a12
--- /dev/null
+++ b/crates/router/src/consts/user.rs
@@ -0,0 +1,8 @@
+#[cfg(feature = "olap")]
+pub const MAX_NAME_LENGTH: usize = 70;
+#[cfg(feature = "olap")]
+pub const MAX_COMPANY_NAME_LENGTH: usize = 70;
+
+// USER ROLES
+#[cfg(any(feature = "olap", feature = "oltp"))]
+pub const ROLE_ID_ORGANIZATION_ADMIN: &str = "org_admin";
diff --git a/crates/router/src/core.rs b/crates/router/src/core.rs
index a3bb3c78915c..b7023fe5ae46 100644
--- a/crates/router/src/core.rs
+++ b/crates/router/src/core.rs
@@ -8,6 +8,7 @@ pub mod customers;
 pub mod disputes;
 pub mod errors;
 pub mod files;
+pub mod gsm;
 pub mod mandate;
 pub mod metrics;
 pub mod payment_link;
@@ -16,6 +17,9 @@ pub mod payments;
 #[cfg(feature = "payouts")]
 pub mod payouts;
 pub mod refunds;
+pub mod routing;
+#[cfg(feature = "olap")]
+pub mod user;
 pub mod utils;
 #[cfg(all(feature = "olap", feature = "kms"))]
 pub mod verification;
diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs
index e30045d4e33e..3a6d96a08e1f 100644
--- a/crates/router/src/core/admin.rs
+++ b/crates/router/src/core/admin.rs
@@ -1,4 +1,9 @@
-use api_models::{admin as admin_types, enums as api_enums};
+use std::str::FromStr;
+
+use api_models::{
+    admin::{self as admin_types},
+    enums as api_enums, routing as routing_types,
+};
 use common_utils::{
     crypto::{generate_cryptographically_secure_random_string, OptionalSecretValue},
     date_time,
@@ -6,6 +11,7 @@ use common_utils::{
     pii,
 };
 use error_stack::{report, FutureExt, ResultExt};
+use futures::future::try_join_all;
 use masking::{PeekInterface, Secret};
 use uuid::Uuid;
 
@@ -14,6 +20,7 @@ use crate::{
     core::{
         errors::{self, RouterResponse, RouterResult, StorageErrorExt},
         payments::helpers,
+        routing::helpers as routing_helpers,
         utils as core_utils,
     },
     db::StorageInterface,
@@ -26,13 +33,11 @@ use crate::{
             types::{self as domain_types, AsyncLift},
         },
         storage::{self, enums::MerchantStorageScheme},
-        transformers::ForeignTryFrom,
+        transformers::{ForeignFrom, ForeignTryFrom},
     },
     utils::{self, OptionExt},
 };
 
-const DEFAULT_ORG_ID: &str = "org_abcdefghijklmn";
-
 #[inline]
 pub fn create_merchant_publishable_key() -> String {
     format!(
@@ -87,7 +92,7 @@ pub async fn create_merchant_account(
             .transpose()?;
 
     if let Some(ref routing_algorithm) = req.routing_algorithm {
-        let _: api::RoutingAlgorithm = routing_algorithm
+        let _: api_models::routing::RoutingAlgorithm = routing_algorithm
             .clone()
             .parse_value("RoutingAlgorithm")
             .change_context(errors::ApiErrorResponse::InvalidDataValue {
@@ -146,6 +151,24 @@ pub async fn create_merchant_account(
         })
         .transpose()?;
 
+    let organization_id = if let Some(organization_id) = req.organization_id.as_ref() {
+        db.find_organization_by_org_id(organization_id)
+            .await
+            .to_not_found_response(errors::ApiErrorResponse::GenericNotFoundError {
+                message: "organization with the given id does not exist".to_string(),
+            })?;
+        organization_id.to_string()
+    } else {
+        let new_organization = api_models::organization::OrganizationNew::new(None);
+        let db_organization = ForeignFrom::foreign_from(new_organization);
+        let organization = db
+            .insert_organization(db_organization)
+            .await
+            .to_duplicate_response(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Error when creating organization")?;
+        organization.org_id
+    };
+
     let mut merchant_account = async {
         Ok(domain::MerchantAccount {
             merchant_id: req.merchant_id,
@@ -158,7 +181,10 @@ pub async fn create_merchant_account(
                 .await?,
             return_url: req.return_url.map(|a| a.to_string()),
             webhook_details,
-            routing_algorithm: req.routing_algorithm,
+            routing_algorithm: Some(serde_json::json!({
+                "algorithm_id": null,
+                "timestamp": 0
+            })),
             sub_merchants_enabled: req.sub_merchants_enabled,
             parent_merchant_id,
             enable_payment_response_hash,
@@ -177,7 +203,7 @@ pub async fn create_merchant_account(
             intent_fulfillment_time: req.intent_fulfillment_time.map(i64::from),
             payout_routing_algorithm: req.payout_routing_algorithm,
             id: None,
-            organization_id: req.organization_id.unwrap_or(DEFAULT_ORG_ID.to_string()),
+            organization_id,
             is_recon_enabled: false,
             default_profile: None,
             recon_status: diesel_models::enums::ReconStatus::NotRequested,
@@ -363,6 +389,66 @@ pub async fn create_business_profile_from_business_labels(
 
     Ok(())
 }
+
+/// For backwards compatibility
+/// If any of the fields of merchant account are updated, then update these fields in business profiles
+pub async fn update_business_profile_cascade(
+    state: AppState,
+    merchant_account_update: api::MerchantAccountUpdate,
+    merchant_id: String,
+) -> RouterResult<()> {
+    if merchant_account_update.return_url.is_some()
+        || merchant_account_update.webhook_details.is_some()
+        || merchant_account_update
+            .enable_payment_response_hash
+            .is_some()
+        || merchant_account_update
+            .redirect_to_merchant_with_http_post
+            .is_some()
+    {
+        // Update these fields in all the business profiles
+        let business_profiles = state
+            .store
+            .list_business_profile_by_merchant_id(&merchant_id)
+            .await
+            .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound {
+                id: merchant_id.to_string(),
+            })?;
+
+        let business_profile_update = admin_types::BusinessProfileUpdate {
+            profile_name: None,
+            return_url: merchant_account_update.return_url,
+            enable_payment_response_hash: merchant_account_update.enable_payment_response_hash,
+            payment_response_hash_key: merchant_account_update.payment_response_hash_key,
+            redirect_to_merchant_with_http_post: merchant_account_update
+                .redirect_to_merchant_with_http_post,
+            webhook_details: merchant_account_update.webhook_details,
+            metadata: None,
+            routing_algorithm: None,
+            intent_fulfillment_time: None,
+            frm_routing_algorithm: None,
+            payout_routing_algorithm: None,
+            applepay_verified_domains: None,
+        };
+
+        let update_futures = business_profiles.iter().map(|business_profile| async {
+            let profile_id = &business_profile.profile_id;
+
+            update_business_profile(
+                state.clone(),
+                profile_id,
+                &merchant_id,
+                business_profile_update.clone(),
+            )
+            .await
+        });
+
+        try_join_all(update_futures).await?;
+    }
+
+    Ok(())
+}
+
 pub async fn merchant_account_update(
     state: AppState,
     merchant_id: &String,
@@ -390,7 +476,7 @@ pub async fn merchant_account_update(
     }
 
     if let Some(ref routing_algorithm) = req.routing_algorithm {
-        let _: api::RoutingAlgorithm = routing_algorithm
+        let _: api_models::routing::RoutingAlgorithm = routing_algorithm
             .clone()
             .parse_value("RoutingAlgorithm")
             .change_context(errors::ApiErrorResponse::InvalidDataValue {
@@ -415,6 +501,7 @@ pub async fn merchant_account_update(
     // In order to support backwards compatibility, if a business_labels are passed in the update
     // call, then create new business_profiles with the profile_name as business_label
     req.primary_business_details
+        .clone()
         .async_map(|primary_business_details| async {
             let _ = create_business_profile_from_business_labels(
                 db,
@@ -428,10 +515,10 @@ pub async fn merchant_account_update(
 
     let key = key_store.key.get_inner().peek();
 
-    let business_profile_id_update = if let Some(profile_id) = req.default_profile {
+    let business_profile_id_update = if let Some(ref profile_id) = req.default_profile {
         if !profile_id.is_empty_after_trim() {
             // Validate whether profile_id passed in request is valid and is linked to the merchant
-            core_utils::validate_and_get_business_profile(db, Some(&profile_id), merchant_id)
+            core_utils::validate_and_get_business_profile(db, Some(profile_id), merchant_id)
                 .await?
                 .map(|business_profile| Some(business_profile.profile_id))
         } else {
@@ -442,6 +529,9 @@ pub async fn merchant_account_update(
         None
     };
 
+    // Update the business profile, This is for backwards compatibility
+    update_business_profile_cascade(state.clone(), req.clone(), merchant_id.to_string()).await?;
+
     let updated_merchant_account = storage::MerchantAccountUpdate::Update {
         merchant_name: req
             .merchant_name
@@ -672,6 +762,9 @@ pub async fn create_payment_connector(
     )
     .await?;
 
+    let routable_connector =
+        api_enums::RoutableConnectors::from_str(&req.connector_name.to_string()).ok();
+
     let business_profile = state
         .store
         .find_business_profile_by_profile_id(&profile_id)
@@ -744,6 +837,37 @@ pub async fn create_payment_connector(
 
     let frm_configs = get_frm_config_as_secret(req.frm_configs);
 
+    // The purpose of this merchant account update is just to update the
+    // merchant account `modified_at` field for KGraph cache invalidation
+    let merchant_account_update = storage::MerchantAccountUpdate::Update {
+        merchant_name: None,
+        merchant_details: None,
+        return_url: None,
+        webhook_details: None,
+        sub_merchants_enabled: None,
+        parent_merchant_id: None,
+        enable_payment_response_hash: None,
+        locker_id: None,
+        payment_response_hash_key: None,
+        primary_business_details: None,
+        metadata: None,
+        publishable_key: None,
+        redirect_to_merchant_with_http_post: None,
+        routing_algorithm: None,
+        intent_fulfillment_time: None,
+        frm_routing_algorithm: None,
+        payout_routing_algorithm: None,
+        default_profile: None,
+        payment_link_config: None,
+    };
+
+    state
+        .store
+        .update_specific_fields_in_merchant(merchant_id, merchant_account_update, &key_store)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("error updating the merchant account when creating payment connector")?;
+
     let merchant_connector_account = domain::MerchantConnectorAccount {
         merchant_id: merchant_id.to_string(),
         connector_type: req.connector_type,
@@ -768,7 +892,7 @@ pub async fn create_payment_connector(
         connector_label: Some(connector_label),
         business_country: req.business_country,
         business_label: req.business_label.clone(),
-        business_sub_label: req.business_sub_label,
+        business_sub_label: req.business_sub_label.clone(),
         created_at: common_utils::date_time::now(),
         modified_at: common_utils::date_time::now(),
         id: None,
@@ -789,17 +913,54 @@ pub async fn create_payment_connector(
         pm_auth_config: req.pm_auth_config.clone(),
     };
 
+    let mut default_routing_config =
+        routing_helpers::get_merchant_default_config(&*state.store, merchant_id).await?;
+
+    let mut default_routing_config_for_profile =
+        routing_helpers::get_merchant_default_config(&*state.clone().store, &profile_id).await?;
+
     let mca = state
         .store
         .insert_merchant_connector_account(merchant_connector_account, &key_store)
         .await
         .to_duplicate_response(
             errors::ApiErrorResponse::DuplicateMerchantConnectorAccount {
-                profile_id,
+                profile_id: profile_id.clone(),
                 connector_name: req.connector_name.to_string(),
             },
         )?;
 
+    if let Some(routable_connector_val) = routable_connector {
+        let choice = routing_types::RoutableConnectorChoice {
+            #[cfg(feature = "backwards_compatibility")]
+            choice_kind: routing_types::RoutableChoiceKind::FullStruct,
+            connector: routable_connector_val,
+            #[cfg(feature = "connector_choice_mca_id")]
+            merchant_connector_id: Some(mca.merchant_connector_id.clone()),
+            #[cfg(not(feature = "connector_choice_mca_id"))]
+            sub_label: req.business_sub_label,
+        };
+
+        if !default_routing_config.contains(&choice) {
+            default_routing_config.push(choice.clone());
+            routing_helpers::update_merchant_default_config(
+                &*state.store,
+                merchant_id,
+                default_routing_config,
+            )
+            .await?;
+        }
+        if !default_routing_config_for_profile.contains(&choice.clone()) {
+            default_routing_config_for_profile.push(choice);
+            routing_helpers::update_merchant_default_config(
+                &*state.store,
+                &profile_id.clone(),
+                default_routing_config_for_profile,
+            )
+            .await?;
+        }
+    }
+
     metrics::MCA_CREATE.add(
         &metrics::CONTEXT,
         1,
@@ -936,8 +1097,8 @@ pub async fn update_payment_connector(
             .await
             .change_context(errors::ApiErrorResponse::InternalServerError)
             .attach_printable("Failed while encrypting data")?,
-        test_mode: mca.test_mode,
-        disabled: mca.disabled,
+        test_mode: req.test_mode,
+        disabled: req.disabled,
         payment_methods_enabled,
         metadata: req.metadata,
         frm_configs,
@@ -1164,7 +1325,7 @@ pub async fn create_business_profile(
         .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
 
     if let Some(ref routing_algorithm) = request.routing_algorithm {
-        let _: api::RoutingAlgorithm = routing_algorithm
+        let _: api_models::routing::RoutingAlgorithm = routing_algorithm
             .clone()
             .parse_value("RoutingAlgorithm")
             .change_context(errors::ApiErrorResponse::InvalidDataValue {
@@ -1276,7 +1437,7 @@ pub async fn update_business_profile(
         .transpose()?;
 
     if let Some(ref routing_algorithm) = request.routing_algorithm {
-        let _: api::RoutingAlgorithm = routing_algorithm
+        let _: api_models::routing::RoutingAlgorithm = routing_algorithm
             .clone()
             .parse_value("RoutingAlgorithm")
             .change_context(errors::ApiErrorResponse::InvalidDataValue {
@@ -1350,6 +1511,10 @@ pub(crate) fn validate_auth_and_metadata_type(
             authorizedotnet::transformers::AuthorizedotnetAuthType::try_from(val)?;
             Ok(())
         }
+        // api_enums::Connector::Bankofamerica => {
+        //     bankofamerica::transformers::BankofamericaAuthType::try_from(val)?;
+        //     Ok(())
+        // } Added as template code for future usage
         api_enums::Connector::Bitpay => {
             bitpay::transformers::BitpayAuthType::try_from(val)?;
             Ok(())
@@ -1506,6 +1671,10 @@ pub(crate) fn validate_auth_and_metadata_type(
             tsys::transformers::TsysAuthType::try_from(val)?;
             Ok(())
         }
+        api_enums::Connector::Volt => {
+            volt::transformers::VoltAuthType::try_from(val)?;
+            Ok(())
+        }
         api_enums::Connector::Wise => {
             wise::transformers::WiseAuthType::try_from(val)?;
             Ok(())
diff --git a/crates/router/src/core/api_keys.rs b/crates/router/src/core/api_keys.rs
index 7bda894826a1..c1ddc43cd65d 100644
--- a/crates/router/src/core/api_keys.rs
+++ b/crates/router/src/core/api_keys.rs
@@ -294,10 +294,10 @@ pub async fn retrieve_api_key(
 #[instrument(skip_all)]
 pub async fn update_api_key(
     state: AppState,
-    merchant_id: &str,
-    key_id: &str,
     api_key: api::UpdateApiKeyRequest,
 ) -> RouterResponse<api::RetrieveApiKeyResponse> {
+    let merchant_id = api_key.merchant_id.clone();
+    let key_id = api_key.key_id.clone();
     let store = state.store.as_ref();
 
     let api_key = store
@@ -313,7 +313,7 @@ pub async fn update_api_key(
     {
         let expiry_reminder_days = state.conf.api_keys.expiry_reminder_days.clone();
 
-        let task_id = generate_task_id_for_api_key_expiry_workflow(key_id);
+        let task_id = generate_task_id_for_api_key_expiry_workflow(&key_id);
         // In order to determine how to update the existing process in the process_tracker table,
         // we need access to the current entry in the table.
         let existing_process_tracker_task = store
@@ -339,7 +339,7 @@ pub async fn update_api_key(
             // If an expiry is set to 'never'
             else {
                 // Process exist in process, revoke it
-                revoke_api_key_expiry_task(store, key_id)
+                revoke_api_key_expiry_task(store, &key_id)
                     .await
                     .into_report()
                     .change_context(errors::ApiErrorResponse::InternalServerError)
diff --git a/crates/router/src/core/cache.rs b/crates/router/src/core/cache.rs
index cba9a5ec303f..a8ca8395a670 100644
--- a/crates/router/src/core/cache.rs
+++ b/crates/router/src/core/cache.rs
@@ -10,7 +10,7 @@ pub async fn invalidate(
     key: &str,
 ) -> CustomResult<services::api::ApplicationResponse<serde_json::Value>, errors::ApiErrorResponse> {
     let store = state.store.as_ref();
-    let result = publish_into_redact_channel(store, CacheKind::All(key.into()))
+    let result = publish_into_redact_channel(store, [CacheKind::All(key.into())])
         .await
         .change_context(errors::ApiErrorResponse::InternalServerError)?;
 
diff --git a/crates/router/src/core/disputes.rs b/crates/router/src/core/disputes.rs
index aaf12acd0a08..535d004e9029 100644
--- a/crates/router/src/core/disputes.rs
+++ b/crates/router/src/core/disputes.rs
@@ -108,6 +108,7 @@ pub async fn accept_dispute(
         &state.conf.connectors,
         &dispute.connector,
         api::GetToken::Connector,
+        dispute.merchant_connector_id.clone(),
     )?;
     let connector_integration: services::BoxedConnectorIntegration<
         '_,
@@ -220,7 +221,9 @@ pub async fn submit_evidence(
         &state.conf.connectors,
         &dispute.connector,
         api::GetToken::Connector,
+        dispute.merchant_connector_id.clone(),
     )?;
+
     let connector_integration: services::BoxedConnectorIntegration<
         '_,
         api::Evidence,
diff --git a/crates/router/src/core/errors.rs b/crates/router/src/core/errors.rs
index 1c062b7035af..810c079987eb 100644
--- a/crates/router/src/core/errors.rs
+++ b/crates/router/src/core/errors.rs
@@ -2,6 +2,8 @@ pub mod api_error_response;
 pub mod customers_error_response;
 pub mod error_handlers;
 pub mod transformers;
+#[cfg(feature = "olap")]
+pub mod user;
 pub mod utils;
 
 use std::fmt::Display;
@@ -13,6 +15,8 @@ use diesel_models::errors as storage_errors;
 pub use redis_interface::errors::RedisError;
 use scheduler::errors as sch_errors;
 use storage_impl::errors as storage_impl_errors;
+#[cfg(feature = "olap")]
+pub use user::*;
 
 pub use self::{
     api_error_response::ApiErrorResponse,
@@ -325,3 +329,49 @@ pub mod error_stack_parsing {
 }
 #[cfg(feature = "detailed_errors")]
 pub use error_stack_parsing::*;
+
+#[derive(Debug, Clone, thiserror::Error)]
+pub enum RoutingError {
+    #[error("Merchant routing algorithm not found in cache")]
+    CacheMiss,
+    #[error("Final connector selection failed")]
+    ConnectorSelectionFailed,
+    #[error("[DSL] Missing required field in payment data: '{field_name}'")]
+    DslMissingRequiredField { field_name: String },
+    #[error("The lock on the DSL cache is most probably poisoned")]
+    DslCachePoisoned,
+    #[error("Expected DSL to be saved in DB but did not find")]
+    DslMissingInDb,
+    #[error("Unable to parse DSL from JSON")]
+    DslParsingError,
+    #[error("Failed to initialize DSL backend")]
+    DslBackendInitError,
+    #[error("Error updating merchant with latest dsl cache contents")]
+    DslMerchantUpdateError,
+    #[error("Error executing the DSL")]
+    DslExecutionError,
+    #[error("Final connector selection failed")]
+    DslFinalConnectorSelectionFailed,
+    #[error("[DSL] Received incorrect selection algorithm as DSL output")]
+    DslIncorrectSelectionAlgorithm,
+    #[error("there was an error saving/retrieving values from the kgraph cache")]
+    KgraphCacheFailure,
+    #[error("failed to refresh the kgraph cache")]
+    KgraphCacheRefreshFailed,
+    #[error("there was an error during the kgraph analysis phase")]
+    KgraphAnalysisError,
+    #[error("'profile_id' was not provided")]
+    ProfileIdMissing,
+    #[error("the profile was not found in the database")]
+    ProfileNotFound,
+    #[error("failed to fetch the fallback config for the merchant")]
+    FallbackConfigFetchFailed,
+    #[error("Invalid connector name received: '{0}'")]
+    InvalidConnectorName(String),
+    #[error("The routing algorithm in merchant account had invalid structure")]
+    InvalidRoutingAlgorithmStructure,
+    #[error("Volume split failed")]
+    VolumeSplitFailed,
+    #[error("Unable to parse metadata")]
+    MetadataParsingError,
+}
diff --git a/crates/router/src/core/errors/user.rs b/crates/router/src/core/errors/user.rs
new file mode 100644
index 000000000000..b4d48365dc84
--- /dev/null
+++ b/crates/router/src/core/errors/user.rs
@@ -0,0 +1,78 @@
+use common_utils::errors::CustomResult;
+
+use crate::services::ApplicationResponse;
+
+pub type UserResult<T> = CustomResult<T, UserErrors>;
+pub type UserResponse<T> = CustomResult<ApplicationResponse<T>, UserErrors>;
+
+#[derive(Debug, thiserror::Error)]
+pub enum UserErrors {
+    #[error("User InternalServerError")]
+    InternalServerError,
+    #[error("InvalidCredentials")]
+    InvalidCredentials,
+    #[error("UserExists")]
+    UserExists,
+    #[error("EmailParsingError")]
+    EmailParsingError,
+    #[error("NameParsingError")]
+    NameParsingError,
+    #[error("PasswordParsingError")]
+    PasswordParsingError,
+    #[error("CompanyNameParsingError")]
+    CompanyNameParsingError,
+    #[error("MerchantAccountCreationError: {0}")]
+    MerchantAccountCreationError(String),
+    #[error("InvalidEmailError")]
+    InvalidEmailError,
+    #[error("DuplicateOrganizationId")]
+    DuplicateOrganizationId,
+}
+
+impl common_utils::errors::ErrorSwitch<api_models::errors::types::ApiErrorResponse> for UserErrors {
+    fn switch(&self) -> api_models::errors::types::ApiErrorResponse {
+        use api_models::errors::types::{ApiError, ApiErrorResponse as AER};
+        let sub_code = "UR";
+        match self {
+            Self::InternalServerError => {
+                AER::InternalServerError(ApiError::new("HE", 0, "Something Went Wrong", None))
+            }
+            Self::InvalidCredentials => AER::Unauthorized(ApiError::new(
+                sub_code,
+                1,
+                "Incorrect email or password",
+                None,
+            )),
+            Self::UserExists => AER::BadRequest(ApiError::new(
+                sub_code,
+                3,
+                "An account already exists with this email",
+                None,
+            )),
+            Self::EmailParsingError => {
+                AER::BadRequest(ApiError::new(sub_code, 7, "Invalid Email", None))
+            }
+            Self::NameParsingError => {
+                AER::BadRequest(ApiError::new(sub_code, 8, "Invalid Name", None))
+            }
+            Self::PasswordParsingError => {
+                AER::BadRequest(ApiError::new(sub_code, 9, "Invalid Password", None))
+            }
+            Self::CompanyNameParsingError => {
+                AER::BadRequest(ApiError::new(sub_code, 14, "Invalid Company Name", None))
+            }
+            Self::MerchantAccountCreationError(error_message) => {
+                AER::InternalServerError(ApiError::new(sub_code, 15, error_message, None))
+            }
+            Self::InvalidEmailError => {
+                AER::BadRequest(ApiError::new(sub_code, 16, "Invalid Email", None))
+            }
+            Self::DuplicateOrganizationId => AER::InternalServerError(ApiError::new(
+                sub_code,
+                21,
+                "An Organization with the id already exists",
+                None,
+            )),
+        }
+    }
+}
diff --git a/crates/router/src/core/files.rs b/crates/router/src/core/files.rs
index 83bfef69e5fd..13c4d3dfdf31 100644
--- a/crates/router/src/core/files.rs
+++ b/crates/router/src/core/files.rs
@@ -44,14 +44,16 @@ pub async fn files_create_core(
         available: false,
         connector_label: None,
         profile_id: None,
+        merchant_connector_id: None,
     };
+
     let file_metadata_object = state
         .store
         .insert_file_metadata(file_new)
         .await
         .change_context(errors::ApiErrorResponse::InternalServerError)
         .attach_printable("Unable to insert file_metadata")?;
-    let (provider_file_id, file_upload_provider, connector_label) =
+    let (provider_file_id, file_upload_provider, profile_id, merchant_connector_id) =
         helpers::upload_and_get_provider_provider_file_id_profile_id(
             &state,
             &merchant_account,
@@ -60,12 +62,14 @@ pub async fn files_create_core(
             file_key.clone(),
         )
         .await?;
-    //Update file metadata
+
+    // Update file metadata
     let update_file_metadata = diesel_models::file::FileMetadataUpdate::Update {
         provider_file_id: Some(provider_file_id),
         file_upload_provider: Some(file_upload_provider),
         available: true,
-        connector_label,
+        profile_id,
+        merchant_connector_id,
     };
     state
         .store
diff --git a/crates/router/src/core/files/helpers.rs b/crates/router/src/core/files/helpers.rs
index 7d7e694b42b9..818067207f40 100644
--- a/crates/router/src/core/files/helpers.rs
+++ b/crates/router/src/core/files/helpers.rs
@@ -79,11 +79,14 @@ pub async fn validate_file_upload(
                 .to_not_found_response(errors::ApiErrorResponse::DisputeNotFound {
                     dispute_id: dispute_id.to_string(),
                 })?;
+            // Connector is not called for validating the file, connector_id can be passed as None safely
             let connector_data = api::ConnectorData::get_connector_by_name(
                 &state.conf.connectors,
                 &dispute.connector,
                 api::GetToken::Connector,
+                None,
             )?;
+
             let validation = connector_data.connector.validate_file_upload(
                 create_file_request.purpose,
                 create_file_request.file_size,
@@ -162,6 +165,7 @@ pub async fn retrieve_file_from_connector(
         &state.conf.connectors,
         connector,
         api::GetToken::Connector,
+        file_metadata.merchant_connector_id.clone(),
     )?;
     let connector_integration: services::BoxedConnectorIntegration<
         '_,
@@ -271,6 +275,7 @@ pub async fn upload_and_get_provider_provider_file_id_profile_id(
         String,
         api_models::enums::FileUploadProvider,
         Option<String>,
+        Option<String>,
     ),
     errors::ApiErrorResponse,
 > {
@@ -289,6 +294,7 @@ pub async fn upload_and_get_provider_provider_file_id_profile_id(
                 &state.conf.connectors,
                 &dispute.connector,
                 api::GetToken::Connector,
+                dispute.merchant_connector_id.clone(),
             )?;
             if connector_data.connector_name.supports_file_storage_module() {
                 let payment_intent = state
@@ -339,6 +345,7 @@ pub async fn upload_and_get_provider_provider_file_id_profile_id(
                 .await
                 .change_context(errors::ApiErrorResponse::InternalServerError)
                 .attach_printable("Failed while calling upload file connector api")?;
+
                 let upload_file_response = response.response.map_err(|err| {
                     errors::ApiErrorResponse::ExternalConnectorError {
                         code: err.code,
@@ -354,6 +361,7 @@ pub async fn upload_and_get_provider_provider_file_id_profile_id(
                         &connector_data.connector_name,
                     )?,
                     payment_intent.profile_id,
+                    payment_attempt.merchant_connector_id,
                 ))
             } else {
                 upload_file(
@@ -367,6 +375,7 @@ pub async fn upload_and_get_provider_provider_file_id_profile_id(
                     file_key,
                     api_models::enums::FileUploadProvider::Router,
                     None,
+                    None,
                 ))
             }
         }
diff --git a/crates/router/src/core/gsm.rs b/crates/router/src/core/gsm.rs
new file mode 100644
index 000000000000..d25860674570
--- /dev/null
+++ b/crates/router/src/core/gsm.rs
@@ -0,0 +1,137 @@
+use api_models::gsm as gsm_api_types;
+use diesel_models::gsm as storage;
+use error_stack::{IntoReport, ResultExt};
+use router_env::{instrument, tracing};
+
+use crate::{
+    core::{
+        errors,
+        errors::{RouterResponse, StorageErrorExt},
+    },
+    db::gsm::GsmInterface,
+    services,
+    types::{self, transformers::ForeignInto},
+    AppState,
+};
+
+#[instrument(skip_all)]
+pub async fn create_gsm_rule(
+    state: AppState,
+    gsm_rule: gsm_api_types::GsmCreateRequest,
+) -> RouterResponse<types::GsmResponse> {
+    let db = state.store.as_ref();
+    GsmInterface::add_gsm_rule(db, gsm_rule.foreign_into())
+        .await
+        .to_duplicate_response(errors::ApiErrorResponse::GenericDuplicateError {
+            message: "GSM with given key already exists in our records".to_string(),
+        })
+        .map(services::ApplicationResponse::Json)
+}
+
+#[instrument(skip_all)]
+pub async fn retrieve_gsm_rule(
+    state: AppState,
+    gsm_request: gsm_api_types::GsmRetrieveRequest,
+) -> RouterResponse<types::GsmResponse> {
+    let db = state.store.as_ref();
+    let gsm_api_types::GsmRetrieveRequest {
+        connector,
+        flow,
+        sub_flow,
+        code,
+        message,
+    } = gsm_request;
+    GsmInterface::find_gsm_rule(db, connector.to_string(), flow, sub_flow, code, message)
+        .await
+        .to_not_found_response(errors::ApiErrorResponse::GenericNotFoundError {
+            message: "GSM with given key does not exist in our records".to_string(),
+        })
+        .map(services::ApplicationResponse::Json)
+}
+
+#[instrument(skip_all)]
+pub async fn update_gsm_rule(
+    state: AppState,
+    gsm_request: gsm_api_types::GsmUpdateRequest,
+) -> RouterResponse<types::GsmResponse> {
+    let db = state.store.as_ref();
+    let gsm_api_types::GsmUpdateRequest {
+        connector,
+        flow,
+        sub_flow,
+        code,
+        message,
+        decision,
+        status,
+        router_error,
+        step_up_possible,
+    } = gsm_request;
+    GsmInterface::update_gsm_rule(
+        db,
+        connector.to_string(),
+        flow,
+        sub_flow,
+        code,
+        message,
+        storage::GatewayStatusMappingUpdate {
+            decision: decision.map(|d| d.to_string()),
+            status,
+            router_error: Some(router_error),
+            step_up_possible,
+        },
+    )
+    .await
+    .to_not_found_response(errors::ApiErrorResponse::GenericNotFoundError {
+        message: "GSM with given key does not exist in our records".to_string(),
+    })
+    .attach_printable("Failed while updating Gsm rule")
+    .map(services::ApplicationResponse::Json)
+}
+
+#[instrument(skip_all)]
+pub async fn delete_gsm_rule(
+    state: AppState,
+    gsm_request: gsm_api_types::GsmDeleteRequest,
+) -> RouterResponse<gsm_api_types::GsmDeleteResponse> {
+    let db = state.store.as_ref();
+    let gsm_api_types::GsmDeleteRequest {
+        connector,
+        flow,
+        sub_flow,
+        code,
+        message,
+    } = gsm_request;
+    match GsmInterface::delete_gsm_rule(
+        db,
+        connector.to_string(),
+        flow.to_owned(),
+        sub_flow.to_owned(),
+        code.to_owned(),
+        message.to_owned(),
+    )
+    .await
+    .to_not_found_response(errors::ApiErrorResponse::GenericNotFoundError {
+        message: "GSM with given key does not exist in our records".to_string(),
+    })
+    .attach_printable("Failed while Deleting Gsm rule")
+    {
+        Ok(is_deleted) => {
+            if is_deleted {
+                Ok(services::ApplicationResponse::Json(
+                    gsm_api_types::GsmDeleteResponse {
+                        gsm_rule_delete: true,
+                        connector,
+                        flow,
+                        sub_flow,
+                        code,
+                    },
+                ))
+            } else {
+                Err(errors::ApiErrorResponse::InternalServerError)
+                    .into_report()
+                    .attach_printable("Failed while Deleting Gsm rule, got response as false")
+            }
+        }
+        Err(err) => Err(err),
+    }
+}
diff --git a/crates/router/src/core/mandate.rs b/crates/router/src/core/mandate.rs
index a1aa1fa9eb4c..55de11549a4b 100644
--- a/crates/router/src/core/mandate.rs
+++ b/crates/router/src/core/mandate.rs
@@ -143,6 +143,7 @@ pub async fn mandate_procedure<F, FData>(
     mut resp: types::RouterData<F, FData, types::PaymentsResponseData>,
     maybe_customer: &Option<domain::Customer>,
     pm_id: Option<String>,
+    merchant_connector_id: Option<String>,
 ) -> errors::RouterResult<types::RouterData<F, FData, types::PaymentsResponseData>>
 where
     FData: MandateBehaviour,
@@ -228,6 +229,7 @@ where
                         network_txn_id,
                         get_insensitive_payment_method_data_if_exists(&resp),
                         mandate_reference,
+                        merchant_connector_id,
                     )? {
                         let connector = new_mandate_data.connector.clone();
                         logger::debug!("{:?}", new_mandate_data);
diff --git a/crates/router/src/core/payment_link.rs b/crates/router/src/core/payment_link.rs
index 2c51fa0c3cbb..2ea6a4d7f219 100644
--- a/crates/router/src/core/payment_link.rs
+++ b/crates/router/src/core/payment_link.rs
@@ -1,6 +1,12 @@
 use api_models::admin as admin_types;
-use common_utils::ext_traits::AsyncExt;
+use common_utils::{
+    consts::{
+        DEFAULT_BACKGROUND_COLOR, DEFAULT_MERCHANT_LOGO, DEFAULT_PRODUCT_IMG, DEFAULT_SDK_THEME,
+    },
+    ext_traits::ValueExt,
+};
 use error_stack::{IntoReport, ResultExt};
+use masking::{PeekInterface, Secret};
 
 use super::errors::{self, RouterResult, StorageErrorExt};
 use crate::{
@@ -43,6 +49,11 @@ pub async fn intiate_payment_link_flow(
         .await
         .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
 
+    let payment_link_id = payment_intent
+        .payment_link_id
+        .get_required_value("payment_link_id")
+        .change_context(errors::ApiErrorResponse::PaymentLinkNotFound)?;
+
     helpers::validate_payment_status_against_not_allowed_statuses(
         &payment_intent.status,
         &[
@@ -55,20 +66,10 @@ pub async fn intiate_payment_link_flow(
         "create payment link",
     )?;
 
-    let fulfillment_time = payment_intent
-        .payment_link_id
-        .as_ref()
-        .async_and_then(|pli| async move {
-            db.find_payment_link_by_payment_link_id(pli)
-                .await
-                .ok()?
-                .fulfilment_time
-                .ok_or(errors::ApiErrorResponse::PaymentNotFound)
-                .ok()
-        })
+    let payment_link = db
+        .find_payment_link_by_payment_link_id(&payment_link_id)
         .await
-        .get_required_value("fulfillment_time")
-        .change_context(errors::ApiErrorResponse::PaymentNotFound)?;
+        .to_not_found_response(errors::ApiErrorResponse::PaymentLinkNotFound)?;
 
     let payment_link_config = merchant_account
         .payment_link_config
@@ -81,12 +82,7 @@ pub async fn intiate_payment_link_flow(
         })
         .transpose()?;
 
-    let order_details = payment_intent
-        .order_details
-        .get_required_value("order_details")
-        .change_context(errors::ApiErrorResponse::MissingRequiredField {
-            field_name: "order_details",
-        })?;
+    let order_details = validate_order_details(payment_intent.order_details)?;
 
     let return_url = if let Some(payment_create_return_url) = payment_intent.return_url {
         payment_create_return_url
@@ -104,25 +100,45 @@ pub async fn intiate_payment_link_flow(
         payment_intent.client_secret,
     )?;
 
+    let (default_sdk_theme, default_background_color) =
+        (DEFAULT_SDK_THEME, DEFAULT_BACKGROUND_COLOR);
+
     let payment_details = api_models::payments::PaymentLinkDetails {
         amount: payment_intent.amount,
         currency,
         payment_id: payment_intent.payment_id,
-        merchant_name: merchant_account.merchant_name,
+        merchant_name: payment_link.custom_merchant_name.unwrap_or(
+            merchant_account
+                .merchant_name
+                .map(|merchant_name| merchant_name.into_inner().peek().to_owned())
+                .unwrap_or_default(),
+        ),
         order_details,
         return_url,
-        expiry: fulfillment_time,
+        expiry: payment_link.fulfilment_time,
         pub_key,
         client_secret,
         merchant_logo: payment_link_config
             .clone()
-            .map(|pl_metadata| pl_metadata.merchant_logo.unwrap_or_default())
+            .map(|pl_config| {
+                pl_config
+                    .merchant_logo
+                    .unwrap_or(DEFAULT_MERCHANT_LOGO.to_string())
+            })
             .unwrap_or_default(),
         max_items_visible_after_collapse: 3,
+        sdk_theme: payment_link_config.clone().and_then(|pl_config| {
+            pl_config
+                .color_scheme
+                .map(|color| color.sdk_theme.unwrap_or(default_sdk_theme.to_string()))
+        }),
     };
 
     let js_script = get_js_script(payment_details)?;
-    let css_script = get_color_scheme_css(payment_link_config.clone());
+    let css_script = get_color_scheme_css(
+        payment_link_config.clone(),
+        default_background_color.to_string(),
+    );
     let payment_link_data = services::PaymentLinkFormData {
         js_script,
         sdk_url: state.conf.payment_link.sdk_url.clone(),
@@ -149,38 +165,21 @@ fn get_js_script(
 
 fn get_color_scheme_css(
     payment_link_config: Option<api_models::admin::PaymentLinkConfig>,
+    default_primary_color: String,
 ) -> String {
-    let (default_primary_color, default_accent_color, default_secondary_color) = (
-        "#C6C7C8".to_string(),
-        "#6A8EF5".to_string(),
-        "#0C48F6".to_string(),
-    );
-
-    let (primary_color, primary_accent_color, secondary_color) = payment_link_config
+    let background_primary_color = payment_link_config
         .and_then(|pl_config| {
             pl_config.color_scheme.map(|color| {
-                (
-                    color.primary_color.unwrap_or(default_primary_color.clone()),
-                    color
-                        .primary_accent_color
-                        .unwrap_or(default_accent_color.clone()),
-                    color
-                        .secondary_color
-                        .unwrap_or(default_secondary_color.clone()),
-                )
+                color
+                    .background_primary_color
+                    .unwrap_or(default_primary_color.clone())
             })
         })
-        .unwrap_or((
-            default_primary_color,
-            default_accent_color,
-            default_secondary_color,
-        ));
+        .unwrap_or(default_primary_color);
 
     format!(
         ":root {{
-      --primary-color: {primary_color};
-      --primary-accent-color: {primary_accent_color};
-      --secondary-color: {secondary_color};
+      --primary-color: {background_primary_color};
     }}"
     )
 }
@@ -203,3 +202,36 @@ fn validate_sdk_requirements(
     })?;
     Ok((pub_key, currency, client_secret))
 }
+
+fn validate_order_details(
+    order_details: Option<Vec<Secret<serde_json::Value>>>,
+) -> Result<
+    Option<Vec<api_models::payments::OrderDetailsWithAmount>>,
+    error_stack::Report<errors::ApiErrorResponse>,
+> {
+    let order_details = order_details
+        .map(|order_details| {
+            order_details
+                .iter()
+                .map(|data| {
+                    data.to_owned()
+                        .parse_value("OrderDetailsWithAmount")
+                        .change_context(errors::ApiErrorResponse::InvalidDataValue {
+                            field_name: "OrderDetailsWithAmount",
+                        })
+                        .attach_printable("Unable to parse OrderDetailsWithAmount")
+                })
+                .collect::<Result<Vec<api_models::payments::OrderDetailsWithAmount>, _>>()
+        })
+        .transpose()?;
+
+    let updated_order_details = order_details.map(|mut order_details| {
+        for order in order_details.iter_mut() {
+            if order.product_img_link.is_none() {
+                order.product_img_link = Some(DEFAULT_PRODUCT_IMG.to_string());
+            }
+        }
+        order_details
+    });
+    Ok(updated_order_details)
+}
diff --git a/crates/router/src/core/payment_link/payment_link.html b/crates/router/src/core/payment_link/payment_link.html
index 462a11d2567e..abacf0998f67 100644
--- a/crates/router/src/core/payment_link/payment_link.html
+++ b/crates/router/src/core/payment_link/payment_link.html
@@ -1,6 +1,8 @@
 <!DOCTYPE html>
 <html>
   <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     {{ hyperloader_sdk_link }}
     <style>
       {{ css_color_scheme }}
@@ -41,11 +43,20 @@
       .hyper-checkout {
         display: flex;
         background-color: #fafafa;
-        height: 100%;
         width: 100%;
+        height: 100%;
         max-width: 1900px;
       }
 
+      #hyper-footer {
+        width: 100vw;
+        display: flex;
+        justify-content: center;
+        background-color: white;
+        z-index: 100;
+        padding: 20px 0;
+      }
+
       .main {
         display: flex;
         flex-flow: column;
@@ -112,8 +123,8 @@
       }
 
       #hyper-checkout-merchant-image > img {
-        height: 48px;
-        width: 48px;
+        height: 40px;
+        width: 40px;
       }
 
       #hyper-checkout-cart-image {
@@ -175,8 +186,8 @@
       }
 
       .hyper-checkout-cart-product-image {
-        height: 72px;
-        width: 72px;
+        height: 56px;
+        width: 56px;
       }
 
       .hyper-checkout-card-item-name {
@@ -234,13 +245,21 @@
         background-color: var(--primary-color);
         box-shadow: 0px 1px 10px #f2f2f2;
         display: flex;
+        flex-flow: column;
         align-items: center;
         justify-content: center;
       }
 
       #payment-form-wrap {
-        min-width: 584px;
-        padding: 50px;
+        min-width: 300px;
+        width: 30vw;
+        padding: 20px;
+        background-color: white;
+        border-radius: 3px;
+      }
+
+      .powered-by-hyper {
+        margin-top: 20px;
       }
 
       #hyper-checkout-sdk-header {
@@ -295,28 +314,13 @@
         margin-top: 10px;
       }
 
-      .checkoutButton {
-        height: 48px;
-        border-radius: 25px;
-        width: 100%;
-        border: transparent;
-        background: var(--secondary-color);
-        color: #ffffff;
-        font-weight: 600;
-        cursor: pointer;
-      }
-
       .page-spinner,
       .page-spinner::before,
-      .page-spinner::after,
-      .spinner,
-      .spinner:before,
-      .spinner:after {
+      .page-spinner::after {
         border-radius: 50%;
       }
 
-      .page-spinner,
-      .spinner {
+      .page-spinner {
         color: #ffffff;
         font-size: 22px;
         text-indent: -99999px;
@@ -331,9 +335,7 @@
       }
 
       .page-spinner::before,
-      .page-spinner::after,
-      .spinner:before,
-      .spinner:after {
+      .page-spinner::after {
         position: absolute;
         content: "";
       }
@@ -347,32 +349,95 @@
       }
 
       #hyper-checkout-status {
-        margin: 40px !important;
+        display: flex;
+        flex-flow: column;
+        font-family: "Montserrat";
+        height: 100%;
+        width: 100%;
+      }
+
+      #hyper-checkout-status-header {
+        max-width: 1200px;
+        border: 1px solid #e6e6e6;
+        border-radius: 3px;
+        padding: 20px;
       }
 
-      .hyper-checkout-status-header {
+      #hyper-checkout-status-header,
+      #hyper-checkout-status-content {
+        width: 100%;
         display: flex;
         align-items: center;
-        font-family: "Montserrat";
+        justify-content: space-between;
         font-size: 24px;
         font-weight: 600;
       }
 
-      #status-img {
-        height: 70px;
+      .hyper-checkout-status-amount {
+        font-family: "Montserrat";
+        font-size: 40px;
+        font-weight: 700;
       }
 
-      #status-date {
-        font-size: 13px;
-        font-weight: 500;
-        color: #53655c;
+      .hyper-checkout-status-merchant-logo {
+        border: 1px solid #e6e6e6;
+        height: 62px;
+        width: 62px;
       }
 
-      #status-details {
-        margin-left: 10px;
+      #hyper-checkout-status-content {
         justify-content: center;
+        align-items: center;
+        flex-flow: column;
+        height: 100%;
+      }
+
+      .hyper-checkout-status-image {
+        height: 200px;
+        width: 200px;
+      }
+
+      .hyper-checkout-status-text {
+        text-align: center;
+        font-size: 28px;
+        font-weight: 600;
+        margin-top: 20px;
+      }
+
+      .hyper-checkout-status-message {
+        text-align: center;
+        font-size: 12px;
+        margin-top: 10px;
+        font-size: 14px;
+        font-weight: 500;
+      }
+
+      .hyper-checkout-status-details {
         display: flex;
         flex-flow: column;
+        margin-top: 20px;
+        border-radius: 3px;
+        border: 1px solid #e6e6e6;
+      }
+
+      .hyper-checkout-status-item {
+        display: flex;
+        align-items: center;
+        padding: 5px 10px;
+        border-bottom: 1px solid #e6e6e6;
+      }
+
+      .hyper-checkout-status-item:last-child {
+        border-bottom: 0;
+      }
+
+      .hyper-checkout-item-header {
+        width: 15ch;
+        font-size: 12px;
+      }
+
+      .hyper-checkout-item-value {
+        font-size: 12px;
       }
 
       @keyframes loading {
@@ -405,19 +470,6 @@
         }
       }
 
-      .spinner:before {
-        width: 10.4px;
-        height: 20.4px;
-        background: var(--primary-color);
-        border-radius: 20.4px 0 0 20.4px;
-        top: -0.2px;
-        left: -0.2px;
-        -webkit-transform-origin: 10.4px 10.2px;
-        transform-origin: 10.4px 10.2px;
-        -webkit-animation: loading 2s infinite ease 1.5s;
-        animation: loading 2s infinite ease 1.5s;
-      }
-
       #payment-message {
         font-size: 12px;
         font-weight: 500;
@@ -426,19 +478,6 @@
         font-family: "Montserrat";
       }
 
-      .spinner:after {
-        width: 10.4px;
-        height: 10.2px;
-        background: var(--primary-color);
-        border-radius: 0 10.2px 10.2px 0;
-        top: -0.1px;
-        left: 10.2px;
-        -webkit-transform-origin: 0px 10.2px;
-        transform-origin: 0px 10.2px;
-        -webkit-animation: loading 2s infinite ease;
-        animation: loading 2s infinite ease;
-      }
-
       #payment-form {
         max-width: 560px;
         width: 100%;
@@ -447,11 +486,6 @@
       }
 
       @media only screen and (max-width: 1200px) {
-        .checkoutButton {
-          width: 95%;
-          background-color: var(--primary-color);
-        }
-
         .hyper-checkout {
           flex-flow: column;
           margin: 0;
@@ -553,31 +587,11 @@
         #payment-form-wrap {
           min-width: 300px;
           padding: 10px;
-          width: 100vw;
+          width: calc(100vw - 20px);
         }
 
-        #hyper-checkout-status {
-          padding: 15px;
-        }
-
-        #status-img {
-          height: 60px;
-        }
-
-        #status-text {
-          font-size: 19px;
-        }
-
-        #status-date {
-          font-size: 12px;
-        }
-
-        .hyper-checkout-item-header {
-          font-size: 11px;
-        }
-
-        .hyper-checkout-item-value {
-          font-size: 17px;
+        #hyper-checkout-status-header {
+          max-width: calc(100% - 40px);
         }
       }
     </style>
@@ -585,22 +599,144 @@
       rel="stylesheet"
       href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800"
     />
+
+    <!-- SVG ICONS -->
+    <svg xmlns="http://www.w3.org/2000/svg" display="none">
+      <defs>
+        <symbol id="cart-icon-small">
+          <mask
+            id="mask0_1_13"
+            style="mask-type: luminance"
+            maskUnits="userSpaceOnUse"
+            x="0"
+            y="0"
+            width="16"
+            height="16"
+          >
+            <path d="M16 0H0V16H16V0Z" fill="white" />
+          </mask>
+          <g mask="url(#mask0_1_13)">
+            <mask
+              id="mask1_1_13"
+              style="mask-type: alpha"
+              maskUnits="userSpaceOnUse"
+              x="0"
+              y="0"
+              width="16"
+              height="16"
+            >
+              <path d="M16 0H0V16H16V0Z" fill="#D9D9D9" />
+            </mask>
+            <g mask="url(#mask1_1_13)">
+              <path
+                d="M3.53716 14.3331C3.20469 14.3331 2.92071 14.2153 2.68525 13.9798C2.44977 13.7444 2.33203 13.4604 2.33203 13.1279V5.53823C2.33203 5.20575 2.44977 4.92178 2.68525 4.68631C2.92071 4.45083 3.20469 4.3331 3.53716 4.3331H4.9987C4.9987 3.50063 5.29058 2.79252 5.87433 2.20876C6.4581 1.62501 7.16621 1.33313 7.99868 1.33313C8.83115 1.33313 9.53927 1.62501 10.123 2.20876C10.7068 2.79252 10.9987 3.50063 10.9987 4.3331H12.4602C12.7927 4.3331 13.0766 4.45083 13.3121 4.68631C13.5476 4.92178 13.6653 5.20575 13.6653 5.53823V13.1279C13.6653 13.4604 13.5476 13.7444 13.3121 13.9798C13.0766 14.2153 12.7927 14.3331 12.4602 14.3331H3.53716ZM3.53716 13.3331H12.4602C12.5115 13.3331 12.5585 13.3117 12.6012 13.269C12.644 13.2262 12.6653 13.1792 12.6653 13.1279V5.53823C12.6653 5.48694 12.644 5.43992 12.6012 5.39718C12.5585 5.35445 12.5115 5.33308 12.4602 5.33308H3.53716C3.48588 5.33308 3.43886 5.35445 3.39611 5.39718C3.35338 5.43992 3.33201 5.48694 3.33201 5.53823V13.1279C3.33201 13.1792 3.35338 13.2262 3.39611 13.269C3.43886 13.3117 3.48588 13.3331 3.53716 13.3331ZM7.99868 8.99973C8.83115 8.99973 9.53927 8.70785 10.123 8.1241C10.7068 7.54033 10.9987 6.83221 10.9987 5.99975H9.99868C9.99868 6.5553 9.80424 7.02752 9.41535 7.41641C9.02646 7.8053 8.55424 7.99975 7.99868 7.99975C7.44313 7.99975 6.9709 7.8053 6.58202 7.41641C6.19313 7.02752 5.99868 6.5553 5.99868 5.99975H4.9987C4.9987 6.83221 5.29058 7.54033 5.87433 8.1241C6.4581 8.70785 7.16621 8.99973 7.99868 8.99973ZM5.99868 4.3331H9.99868C9.99868 3.77754 9.80424 3.30532 9.41535 2.91643C9.02646 2.52754 8.55424 2.3331 7.99868 2.3331C7.44313 2.3331 6.9709 2.52754 6.58202 2.91643C6.19313 3.30532 5.99868 3.77754 5.99868 4.3331Z"
+                fill="#333333"
+              />
+            </g>
+          </g>
+        </symbol>
+        <symbol id="cart-icon-big">
+          <mask
+            id="mask0_1_13"
+            style="mask-type: luminance"
+            maskUnits="userSpaceOnUse"
+            x="0"
+            y="0"
+            width="30"
+            height="30"
+          >
+            <path d="M30 0H0V30H30V0Z" fill="white" />
+          </mask>
+          <g mask="url(#mask0_1_13)">
+            <mask
+              id="mask1_1_13"
+              style="mask-type: alpha"
+              maskUnits="userSpaceOnUse"
+              x="0"
+              y="0"
+              width="30"
+              height="30"
+            >
+              <path d="M30 0H0V30H30V0Z" fill="#D9D9D9" />
+            </mask>
+            <g mask="url(#mask1_1_13)">
+              <path
+                d="M6.63218 26.8746C6.0088 26.8746 5.47633 26.6537 5.03485 26.2121C4.59332 25.7708 4.37256 25.2383 4.37256 24.6148V10.3842C4.37256 9.76078 4.59332 9.22834 5.03485 8.78683C5.47633 8.34531 6.0088 8.12456 6.63218 8.12456H9.37257C9.37257 6.56368 9.91984 5.23597 11.0144 4.14142C12.1089 3.04689 13.4366 2.49962 14.9975 2.49962C16.5584 2.49962 17.8861 3.04689 18.9806 4.14142C20.0753 5.23597 20.6226 6.56368 20.6226 8.12456H23.3629C23.9863 8.12456 24.5186 8.34531 24.9602 8.78683C25.4018 9.22834 25.6224 9.76078 25.6224 10.3842V24.6148C25.6224 25.2383 25.4018 25.7708 24.9602 26.2121C24.5186 26.6537 23.9863 26.8746 23.3629 26.8746H6.63218ZM6.63218 24.9996H23.3629C23.4591 24.9996 23.5472 24.9594 23.6273 24.8794C23.7075 24.7991 23.7474 24.711 23.7474 24.6148V10.3842C23.7474 10.288 23.7075 10.1999 23.6273 10.1197C23.5472 10.0396 23.4591 9.99952 23.3629 9.99952H6.63218C6.53603 9.99952 6.44786 10.0396 6.36771 10.1197C6.28759 10.1999 6.24752 10.288 6.24752 10.3842V24.6148C6.24752 24.711 6.28759 24.7991 6.36771 24.8794C6.44786 24.9594 6.53603 24.9996 6.63218 24.9996ZM14.9975 16.8745C16.5584 16.8745 17.8861 16.3272 18.9806 15.2327C20.0753 14.1381 20.6226 12.8104 20.6226 11.2495H18.7475C18.7475 12.2912 18.383 13.1766 17.6538 13.9058C16.9246 14.6349 16.0392 14.9995 14.9975 14.9995C13.9559 14.9995 13.0704 14.6349 12.3413 13.9058C11.6121 13.1766 11.2475 12.2912 11.2475 11.2495H9.37257C9.37257 12.8104 9.91984 14.1381 11.0144 15.2327C12.1089 16.3272 13.4366 16.8745 14.9975 16.8745ZM11.2475 8.12456H18.7475C18.7475 7.08289 18.383 6.19747 17.6538 5.46831C16.9246 4.73914 16.0392 4.37456 14.9975 4.37456C13.9559 4.37456 13.0704 4.73914 12.3413 5.46831C11.6121 6.19747 11.2475 7.08289 11.2475 8.12456Z"
+                fill="#333333"
+              />
+            </g>
+          </g>
+        </symbol>
+        <symbol id="cart-close">
+          <path
+            d="M 9.15625 6.3125 L 6.3125 9.15625 L 22.15625 25 L 6.21875 40.96875 L 9.03125 43.78125 L 25 27.84375 L 40.9375 43.78125 L 43.78125 40.9375 L 27.84375 25 L 43.6875 9.15625 L 40.84375 6.3125 L 25 22.15625 Z"
+          ></path>
+        </symbol>
+        <symbol id="hyperswitch-brand">
+          <path
+            opacity="0.4"
+            d="M0.791016 11.7578H1.64062V9.16992H1.71875C2.00684 9.73145 2.63672 10.0928 3.35938 10.0928C4.69727 10.0928 5.56641 9.02344 5.56641 7.37305V7.36328C5.56641 5.72266 4.69238 4.64355 3.35938 4.64355C2.62695 4.64355 2.04102 4.99023 1.71875 5.57617H1.64062V4.73633H0.791016V11.7578ZM3.16406 9.34082C2.20703 9.34082 1.62109 8.58887 1.62109 7.37305V7.36328C1.62109 6.14746 2.20703 5.39551 3.16406 5.39551C4.12598 5.39551 4.69727 6.1377 4.69727 7.36328V7.37305C4.69727 8.59863 4.12598 9.34082 3.16406 9.34082ZM8.85762 10.0928C10.3566 10.0928 11.2844 9.05762 11.2844 7.37305V7.36328C11.2844 5.67383 10.3566 4.64355 8.85762 4.64355C7.35859 4.64355 6.43086 5.67383 6.43086 7.36328V7.37305C6.43086 9.05762 7.35859 10.0928 8.85762 10.0928ZM8.85762 9.34082C7.86152 9.34082 7.3 8.61328 7.3 7.37305V7.36328C7.3 6.11816 7.86152 5.39551 8.85762 5.39551C9.85371 5.39551 10.4152 6.11816 10.4152 7.36328V7.37305C10.4152 8.61328 9.85371 9.34082 8.85762 9.34082ZM13.223 10H14.0727L15.2445 5.92773H15.3227L16.4994 10H17.3539L18.8285 4.73633H17.9838L16.9486 8.94531H16.8705L15.6938 4.73633H14.8881L13.7113 8.94531H13.6332L12.598 4.73633H11.7484L13.223 10ZM21.7047 10.0928C22.9449 10.0928 23.6969 9.38965 23.8775 8.67676L23.8873 8.6377H23.0377L23.0182 8.68164C22.8766 8.99902 22.4371 9.33594 21.7242 9.33594C20.7867 9.33594 20.1861 8.70117 20.1617 7.6123H23.9508V7.28027C23.9508 5.70801 23.0816 4.64355 21.651 4.64355C20.2203 4.64355 19.2926 5.75684 19.2926 7.38281V7.3877C19.2926 9.03809 20.2008 10.0928 21.7047 10.0928ZM21.6461 5.40039C22.4225 5.40039 22.9986 5.89355 23.0865 6.93359H20.1764C20.2691 5.93262 20.8648 5.40039 21.6461 5.40039ZM25.0691 10H25.9188V6.73828C25.9188 5.9668 26.4949 5.4541 27.3055 5.4541C27.491 5.4541 27.6521 5.47363 27.8279 5.50293V4.67773C27.7449 4.66309 27.5643 4.64355 27.4031 4.64355C26.6902 4.64355 26.1971 4.96582 25.9969 5.51758H25.9188V4.73633H25.0691V10ZM30.6797 10.0928C31.9199 10.0928 32.6719 9.38965 32.8525 8.67676L32.8623 8.6377H32.0127L31.9932 8.68164C31.8516 8.99902 31.4121 9.33594 30.6992 9.33594C29.7617 9.33594 29.1611 8.70117 29.1367 7.6123H32.9258V7.28027C32.9258 5.70801 32.0566 4.64355 30.626 4.64355C29.1953 4.64355 28.2676 5.75684 28.2676 7.38281V7.3877C28.2676 9.03809 29.1758 10.0928 30.6797 10.0928ZM30.6211 5.40039C31.3975 5.40039 31.9736 5.89355 32.0615 6.93359H29.1514C29.2441 5.93262 29.8398 5.40039 30.6211 5.40039ZM35.9875 10.0928C36.7199 10.0928 37.3059 9.74609 37.6281 9.16016H37.7062V10H38.5559V2.64648H37.7062V5.56641H37.6281C37.34 5.00488 36.7102 4.64355 35.9875 4.64355C34.6496 4.64355 33.7805 5.71289 33.7805 7.36328V7.37305C33.7805 9.01367 34.6545 10.0928 35.9875 10.0928ZM36.1828 9.34082C35.2209 9.34082 34.6496 8.59863 34.6496 7.37305V7.36328C34.6496 6.1377 35.2209 5.39551 36.1828 5.39551C37.1398 5.39551 37.7258 6.14746 37.7258 7.36328V7.37305C37.7258 8.58887 37.1398 9.34082 36.1828 9.34082ZM45.2164 10.0928C46.5494 10.0928 47.4234 9.01367 47.4234 7.37305V7.36328C47.4234 5.71289 46.5543 4.64355 45.2164 4.64355C44.4938 4.64355 43.8639 5.00488 43.5758 5.56641H43.4977V2.64648H42.648V10H43.4977V9.16016H43.5758C43.898 9.74609 44.484 10.0928 45.2164 10.0928ZM45.0211 9.34082C44.0641 9.34082 43.4781 8.58887 43.4781 7.37305V7.36328C43.4781 6.14746 44.0641 5.39551 45.0211 5.39551C45.983 5.39551 46.5543 6.1377 46.5543 7.36328V7.37305C46.5543 8.59863 45.983 9.34082 45.0211 9.34082ZM48.7957 11.8457C49.7283 11.8457 50.1629 11.5039 50.5975 10.3223L52.6531 4.73633H51.7596L50.3191 9.06738H50.241L48.7957 4.73633H47.8875L49.8357 10.0049L49.7381 10.3174C49.5477 10.9229 49.2547 11.1426 48.7713 11.1426C48.6541 11.1426 48.5223 11.1377 48.4197 11.1182V11.8164C48.5369 11.8359 48.6834 11.8457 48.7957 11.8457Z"
+            fill="currentColor"
+          ></path>
+          <g opacity="0.6">
+            <path
+              d="M78.42 6.9958C78.42 9.15638 77.085 10.4444 75.2379 10.4444C74.2164 10.4444 73.3269 10.0276 72.9206 9.33816V12.9166H71.4929V3.65235H72.8018L72.9193 4.66772C73.3256 3.97825 74.189 3.5225 75.2366 3.5225C77.017 3.5225 78.4186 4.75861 78.4186 6.9971L78.42 6.9958ZM76.94 6.9958C76.94 5.62985 76.1288 4.78328 74.9492 4.78328C73.8232 4.77029 72.9598 5.62855 72.9598 7.00878C72.9598 8.38901 73.8246 9.18235 74.9492 9.18235C76.0739 9.18235 76.94 8.36304 76.94 6.9958Z"
+              fill="currentColor"
+            ></path>
+            <path
+              d="M86.0132 7.3736H80.8809C80.9071 8.62268 81.7313 9.2732 82.7789 9.2732C83.564 9.2732 84.2197 8.90834 84.494 8.17992H85.9479C85.5939 9.53288 84.3895 10.4444 82.7528 10.4444C80.749 10.4444 79.4271 9.06545 79.4271 6.96978C79.4271 4.87412 80.749 3.50818 82.7397 3.50818C84.7305 3.50818 86.0132 4.83517 86.0132 6.83994V7.3736ZM80.894 6.38419H84.5594C84.481 5.226 83.709 4.6404 82.7397 4.6404C81.7705 4.6404 80.9985 5.226 80.894 6.38419Z"
+              fill="currentColor"
+            ></path>
+            <path
+              d="M88.5407 3.65204C87.8745 3.65204 87.335 4.18829 87.335 4.85048V10.3156H88.7758V5.22703C88.7758 5.06213 88.9104 4.92709 89.0776 4.92709H91.2773V3.65204H88.5407Z"
+              fill="currentColor"
+            ></path>
+            <path
+              d="M69.1899 3.63908L67.3442 9.17039L65.3535 3.65207H63.8082L66.3606 10.2247C66.439 10.4325 66.4782 10.6026 66.4782 10.7713C66.4782 10.8635 66.469 10.9479 66.4533 11.0258L66.4494 11.0401C66.4403 11.0817 66.4298 11.1206 66.4168 11.1583L66.3201 11.5102C66.2966 11.5971 66.2169 11.6569 66.1268 11.6569H64.0956V12.9189H65.5755C66.5709 12.9189 67.3952 12.6852 67.8667 11.3829L70.6817 3.65207L69.1886 3.63908H69.1899Z"
+              fill="currentColor"
+            ></path>
+            <path
+              d="M57 10.3144H58.4264V6.72299C58.4264 5.60375 59.0417 4.82339 60.1807 4.82339C61.1761 4.81041 61.7913 5.396 61.7913 6.68404V10.3144H63.2191V6.46201C63.2191 4.18457 61.8188 3.50809 60.5478 3.50809C59.5785 3.50809 58.8196 3.88593 58.4264 4.51047V0.919022H57V10.3144Z"
+              fill="currentColor"
+            ></path>
+            <path
+              d="M93.1623 8.29808C93.1753 8.98755 93.8167 9.39136 94.6945 9.39136C95.5723 9.39136 96.0948 9.06545 96.0948 8.47986C96.0948 7.97218 95.8336 7.69951 95.0733 7.58135L93.7253 7.34763C92.4164 7.1269 91.9057 6.44912 91.9057 5.49997C91.9057 4.30282 93.097 3.52246 94.6161 3.52246C96.2529 3.52246 97.4442 4.30282 97.4572 5.63111H96.0439C96.0308 4.95463 95.4417 4.57679 94.6174 4.57679C93.7932 4.57679 93.3347 4.90269 93.3347 5.44933C93.3347 5.93105 93.6756 6.15178 94.4215 6.28162L95.7434 6.51534C96.987 6.73607 97.563 7.34763 97.563 8.35002C97.563 9.72895 96.2803 10.4457 94.722 10.4457C92.9546 10.4457 91.7633 9.60041 91.7372 8.29808H93.1649H93.1623Z"
+              fill="currentColor"
+            ></path>
+            <path
+              d="M100.808 8.75352L102.327 3.652H103.82L105.313 8.75352L106.583 3.652H108.089L106.191 10.3155H104.58L103.061 5.23997L101.529 10.3155H99.9052L97.9941 3.652H99.5002L100.809 8.75352H100.808Z"
+              fill="currentColor"
+            ></path>
+            <path
+              d="M108.926 0.918945H110.511V2.40305H108.926V0.918945ZM109.005 3.65214H110.431V10.3157H109.005V3.65214Z"
+              fill="currentColor"
+            ></path>
+            <path
+              d="M119.504 4.7452C118.391 4.7452 117.632 5.55152 117.632 6.9707C117.632 8.46779 118.417 9.19621 119.465 9.19621C120.302 9.19621 120.919 8.72748 121.193 7.84325H122.712C122.371 9.45719 121.141 10.4466 119.491 10.4466C117.502 10.4466 116.165 9.06767 116.165 6.972C116.165 4.87634 117.5 3.51039 119.504 3.51039C121.141 3.51039 122.358 4.43487 122.712 6.04752H121.167C120.932 5.21523 120.289 4.7465 119.504 4.7465V4.7452Z"
+              fill="currentColor"
+            ></path>
+            <path
+              d="M113.959 9.05208C113.875 9.05208 113.809 8.98456 113.809 8.90276V4.91399H115.367V3.65191H113.809V1.86787H112.382V3.02607C112.382 3.44287 112.252 3.65062 111.833 3.65062H111.256V4.91269H112.382V8.50414C112.382 9.66234 113.024 10.3128 114.189 10.3128H115.354V9.05078H113.96L113.959 9.05208Z"
+              fill="currentColor"
+            ></path>
+            <path
+              d="M127.329 3.50801C126.359 3.50801 125.601 3.88585 125.207 4.5104V0.918945H123.781V10.3144H125.207V6.72292C125.207 5.60367 125.823 4.82332 126.962 4.82332C127.957 4.81033 128.572 5.39592 128.572 6.68397V10.3144H130V6.46193C130 4.18449 128.6 3.50801 127.329 3.50801Z"
+              fill="currentColor"
+            ></path>
+          </g>
+        </symbol>
+      </defs>
+    </svg>
   </head>
 
   <body onload="showSDK()">
     <div class="page-spinner hidden" id="page-spinner"></div>
     <div class="hyper-checkout">
       <div class="main hidden" id="hyper-checkout-status">
-        <div class="hyper-checkout-status-header">
-          <img id="status-img" />
-          <div id="status-details">
-            <div id="status-text"></div>
-            <div id="status-date"></div>
-          </div>
-        </div>
-        <div id="hyper-checkout-status-items"></div>
+        <div id="hyper-checkout-status-header"></div>
+        <div id="hyper-checkout-status-content"></div>
       </div>
-      <div class="main" id="hyper-checkout-details">
+      <div class="main hidden" id="hyper-checkout-details">
         <div class="hyper-checkout-payment">
           <div class="hyper-checkout-payment-content-details">
             <div id="hyper-checkout-payment-context">
@@ -613,40 +749,27 @@
                 onclick="viewCartInMobileView()"
               >
                 <svg
-                  fill="#000000"
-                  version="1.1"
-                  id="Capa_1"
+                  width="30"
+                  height="30"
+                  viewBox="0 0 30 30"
+                  fill="none"
                   xmlns="http://www.w3.org/2000/svg"
-                  xmlns:xlink="http://www.w3.org/1999/xlink"
-                  width="30px"
-                  height="30px"
-                  viewBox="0 0 902.86 902.86"
-                  xml:space="preserve"
+                  class="cart-icon"
                 >
-                  <g>
-                    <g>
-                      <path
-                        d="M671.504,577.829l110.485-432.609H902.86v-68H729.174L703.128,179.2L0,178.697l74.753,399.129h596.751V577.829z
-   M685.766,247.188l-67.077,262.64H131.199L81.928,246.756L685.766,247.188z"
-                      ></path>
-                      <path
-                        d="M578.418,825.641c59.961,0,108.743-48.783,108.743-108.744s-48.782-108.742-108.743-108.742H168.717
-  c-59.961,0-108.744,48.781-108.744,108.742s48.782,108.744,108.744,108.744c59.962,0,108.743-48.783,108.743-108.744
-  c0-14.4-2.821-28.152-7.927-40.742h208.069c-5.107,12.59-7.928,26.342-7.928,40.742
-  C469.675,776.858,518.457,825.641,578.418,825.641z M209.46,716.897c0,22.467-18.277,40.744-40.743,40.744
-  c-22.466,0-40.744-18.277-40.744-40.744c0-22.465,18.277-40.742,40.744-40.742C191.183,676.155,209.46,694.432,209.46,716.897z
-   M619.162,716.897c0,22.467-18.277,40.744-40.743,40.744s-40.743-18.277-40.743-40.744c0-22.465,18.277-40.742,40.743-40.742
-  S619.162,694.432,619.162,716.897z"
-                      ></path>
-                    </g>
-                  </g>
+                  <use
+                    xlink:href="#cart-icon-big"
+                    x="0"
+                    y="0"
+                    width="30"
+                    height="30"
+                  />
                 </svg>
               </div>
             </div>
           </div>
           <div id="hyper-checkout-payment-footer"></div>
         </div>
-        <div id="hyper-checkout-cart" class="hidden">
+        <div id="hyper-checkout-cart" class="">
           <div class="hyper-checkout-cart-header">
             <svg
               width="16"
@@ -656,51 +779,38 @@
               xmlns="http://www.w3.org/2000/svg"
               class="cart-icon"
             >
-              <g clip-path="url(#clip0_11421_6708)">
-                <mask
-                  id="mask0_11421_6708"
-                  style="mask-type: alpha"
-                  maskUnits="userSpaceOnUse"
-                  x="0"
-                  y="0"
-                  width="16"
-                  height="16"
-                >
-                  <rect width="16" height="16" fill="#D9D9D9"></rect>
-                </mask>
-                <g mask="url(#mask0_11421_6708)">
-                  <path
-                    d="M3.53716 14.3331C3.20469 14.3331 2.92071 14.2153 2.68525 13.9798C2.44977 13.7444 2.33203 13.4604 2.33203 13.1279V5.53823C2.33203 5.20575 2.44977 4.92178 2.68525 4.68631C2.92071 4.45083 3.20469 4.3331 3.53716 4.3331H4.9987C4.9987 3.50063 5.29058 2.79252 5.87433 2.20876C6.4581 1.62501 7.16621 1.33313 7.99868 1.33313C8.83115 1.33313 9.53927 1.62501 10.123 2.20876C10.7068 2.79252 10.9987 3.50063 10.9987 4.3331H12.4602C12.7927 4.3331 13.0766 4.45083 13.3121 4.68631C13.5476 4.92178 13.6653 5.20575 13.6653 5.53823V13.1279C13.6653 13.4604 13.5476 13.7444 13.3121 13.9798C13.0766 14.2153 12.7927 14.3331 12.4602 14.3331H3.53716ZM3.53716 13.3331H12.4602C12.5115 13.3331 12.5585 13.3117 12.6012 13.269C12.644 13.2262 12.6653 13.1792 12.6653 13.1279V5.53823C12.6653 5.48694 12.644 5.43992 12.6012 5.39718C12.5585 5.35445 12.5115 5.33308 12.4602 5.33308H3.53716C3.48588 5.33308 3.43886 5.35445 3.39611 5.39718C3.35338 5.43992 3.33201 5.48694 3.33201 5.53823V13.1279C3.33201 13.1792 3.35338 13.2262 3.39611 13.269C3.43886 13.3117 3.48588 13.3331 3.53716 13.3331ZM7.99868 8.99973C8.83115 8.99973 9.53927 8.70785 10.123 8.1241C10.7068 7.54033 10.9987 6.83221 10.9987 5.99975H9.99868C9.99868 6.5553 9.80424 7.02752 9.41535 7.41641C9.02646 7.8053 8.55424 7.99975 7.99868 7.99975C7.44313 7.99975 6.9709 7.8053 6.58202 7.41641C6.19313 7.02752 5.99868 6.5553 5.99868 5.99975H4.9987C4.9987 6.83221 5.29058 7.54033 5.87433 8.1241C6.4581 8.70785 7.16621 8.99973 7.99868 8.99973ZM5.99868 4.3331H9.99868C9.99868 3.77754 9.80424 3.30532 9.41535 2.91643C9.02646 2.52754 8.55424 2.3331 7.99868 2.3331C7.44313 2.3331 6.9709 2.52754 6.58202 2.91643C6.19313 3.30532 5.99868 3.77754 5.99868 4.3331Z"
-                    fill="#333333"
-                  ></path>
-                </g>
-              </g>
-              <defs>
-                <clipPath id="clip0_11421_6708">
-                  <rect width="16" height="16" fill="white"></rect>
-                </clipPath>
-              </defs>
+              <use
+                xlink:href="#cart-icon-small"
+                x="0"
+                y="0"
+                width="16"
+                height="16"
+              />
             </svg>
             <span>Your Cart</span>
             <svg
               xmlns="http://www.w3.org/2000/svg"
               viewBox="0 0 50 50"
-              width="25px"
-              height="25px"
+              width="25"
+              height="25"
               class="cart-close"
               onclick="hideCartInMobileView()"
             >
-              <path
-                d="M 9.15625 6.3125 L 6.3125 9.15625 L 22.15625 25 L 6.21875 40.96875 L 9.03125 43.78125 L 25 27.84375 L 40.9375 43.78125 L 43.78125 40.9375 L 27.84375 25 L 43.6875 9.15625 L 40.84375 6.3125 L 25 22.15625 Z"
-              ></path>
+              <use
+                xlink:href="#cart-close"
+                x="0"
+                y="0"
+                width="50"
+                height="50"
+              />
             </svg>
           </div>
           <div id="hyper-checkout-cart-items" class="hide-scrollbar"></div>
         </div>
       </div>
-      <div class="hyper-checkout-sdk" id="hyper-checkout-sdk">
+      <div class="hyper-checkout-sdk hidden" id="hyper-checkout-sdk">
         <div id="payment-form-wrap">
-          <form id="payment-form" onsubmit="handleSubmit(); return false;">
+          <form id="payment-form">
             <div id="unified-checkout">
               <div
                 id="orca-element-unified-checkout"
@@ -714,674 +824,674 @@
                   src="http://localhost:9050/?componentName=payment"
                   allow="payment *"
                   style="
-                    border: 0px none;
+                    border: 0px;
                     transition: height 0.35s ease 0s, opacity 0.4s ease 0.1s;
-                    height: 338px;
+                    height: 368px;
                   "
                   width="100%"
                 ></iframe>
               </div>
             </div>
-            <button id="submit" class="checkoutButton payNow">
-              <div class="spinner hidden" id="spinner"></div>
-              <span id="button-text">Pay now</span>
-            </button>
             <div id="payment-message" class="hidden"></div>
           </form>
         </div>
+        <div class="powered-by-hyper">
+          <svg class="fill-current" height="18" width="130" transform="">
+            <use
+              xlink:href="#hyperswitch-brand"
+              x="0"
+              y="0"
+              height="18"
+              width="130"
+            />
+          </svg>
+        </div>
       </div>
     </div>
     <div id="hyper-footer" class="hidden">
-      <svg class="fill-current" height="18px" width="130px" transform="">
-        <path
-          opacity="0.4"
-          d="M0.791016 11.7578H1.64062V9.16992H1.71875C2.00684 9.73145 2.63672 10.0928 3.35938 10.0928C4.69727 10.0928 5.56641 9.02344 5.56641 7.37305V7.36328C5.56641 5.72266 4.69238 4.64355 3.35938 4.64355C2.62695 4.64355 2.04102 4.99023 1.71875 5.57617H1.64062V4.73633H0.791016V11.7578ZM3.16406 9.34082C2.20703 9.34082 1.62109 8.58887 1.62109 7.37305V7.36328C1.62109 6.14746 2.20703 5.39551 3.16406 5.39551C4.12598 5.39551 4.69727 6.1377 4.69727 7.36328V7.37305C4.69727 8.59863 4.12598 9.34082 3.16406 9.34082ZM8.85762 10.0928C10.3566 10.0928 11.2844 9.05762 11.2844 7.37305V7.36328C11.2844 5.67383 10.3566 4.64355 8.85762 4.64355C7.35859 4.64355 6.43086 5.67383 6.43086 7.36328V7.37305C6.43086 9.05762 7.35859 10.0928 8.85762 10.0928ZM8.85762 9.34082C7.86152 9.34082 7.3 8.61328 7.3 7.37305V7.36328C7.3 6.11816 7.86152 5.39551 8.85762 5.39551C9.85371 5.39551 10.4152 6.11816 10.4152 7.36328V7.37305C10.4152 8.61328 9.85371 9.34082 8.85762 9.34082ZM13.223 10H14.0727L15.2445 5.92773H15.3227L16.4994 10H17.3539L18.8285 4.73633H17.9838L16.9486 8.94531H16.8705L15.6938 4.73633H14.8881L13.7113 8.94531H13.6332L12.598 4.73633H11.7484L13.223 10ZM21.7047 10.0928C22.9449 10.0928 23.6969 9.38965 23.8775 8.67676L23.8873 8.6377H23.0377L23.0182 8.68164C22.8766 8.99902 22.4371 9.33594 21.7242 9.33594C20.7867 9.33594 20.1861 8.70117 20.1617 7.6123H23.9508V7.28027C23.9508 5.70801 23.0816 4.64355 21.651 4.64355C20.2203 4.64355 19.2926 5.75684 19.2926 7.38281V7.3877C19.2926 9.03809 20.2008 10.0928 21.7047 10.0928ZM21.6461 5.40039C22.4225 5.40039 22.9986 5.89355 23.0865 6.93359H20.1764C20.2691 5.93262 20.8648 5.40039 21.6461 5.40039ZM25.0691 10H25.9188V6.73828C25.9188 5.9668 26.4949 5.4541 27.3055 5.4541C27.491 5.4541 27.6521 5.47363 27.8279 5.50293V4.67773C27.7449 4.66309 27.5643 4.64355 27.4031 4.64355C26.6902 4.64355 26.1971 4.96582 25.9969 5.51758H25.9188V4.73633H25.0691V10ZM30.6797 10.0928C31.9199 10.0928 32.6719 9.38965 32.8525 8.67676L32.8623 8.6377H32.0127L31.9932 8.68164C31.8516 8.99902 31.4121 9.33594 30.6992 9.33594C29.7617 9.33594 29.1611 8.70117 29.1367 7.6123H32.9258V7.28027C32.9258 5.70801 32.0566 4.64355 30.626 4.64355C29.1953 4.64355 28.2676 5.75684 28.2676 7.38281V7.3877C28.2676 9.03809 29.1758 10.0928 30.6797 10.0928ZM30.6211 5.40039C31.3975 5.40039 31.9736 5.89355 32.0615 6.93359H29.1514C29.2441 5.93262 29.8398 5.40039 30.6211 5.40039ZM35.9875 10.0928C36.7199 10.0928 37.3059 9.74609 37.6281 9.16016H37.7062V10H38.5559V2.64648H37.7062V5.56641H37.6281C37.34 5.00488 36.7102 4.64355 35.9875 4.64355C34.6496 4.64355 33.7805 5.71289 33.7805 7.36328V7.37305C33.7805 9.01367 34.6545 10.0928 35.9875 10.0928ZM36.1828 9.34082C35.2209 9.34082 34.6496 8.59863 34.6496 7.37305V7.36328C34.6496 6.1377 35.2209 5.39551 36.1828 5.39551C37.1398 5.39551 37.7258 6.14746 37.7258 7.36328V7.37305C37.7258 8.58887 37.1398 9.34082 36.1828 9.34082ZM45.2164 10.0928C46.5494 10.0928 47.4234 9.01367 47.4234 7.37305V7.36328C47.4234 5.71289 46.5543 4.64355 45.2164 4.64355C44.4938 4.64355 43.8639 5.00488 43.5758 5.56641H43.4977V2.64648H42.648V10H43.4977V9.16016H43.5758C43.898 9.74609 44.484 10.0928 45.2164 10.0928ZM45.0211 9.34082C44.0641 9.34082 43.4781 8.58887 43.4781 7.37305V7.36328C43.4781 6.14746 44.0641 5.39551 45.0211 5.39551C45.983 5.39551 46.5543 6.1377 46.5543 7.36328V7.37305C46.5543 8.59863 45.983 9.34082 45.0211 9.34082ZM48.7957 11.8457C49.7283 11.8457 50.1629 11.5039 50.5975 10.3223L52.6531 4.73633H51.7596L50.3191 9.06738H50.241L48.7957 4.73633H47.8875L49.8357 10.0049L49.7381 10.3174C49.5477 10.9229 49.2547 11.1426 48.7713 11.1426C48.6541 11.1426 48.5223 11.1377 48.4197 11.1182V11.8164C48.5369 11.8359 48.6834 11.8457 48.7957 11.8457Z"
-          fill="currentColor"
-        ></path>
-        <g opacity="0.6">
-          <path
-            d="M78.42 6.9958C78.42 9.15638 77.085 10.4444 75.2379 10.4444C74.2164 10.4444 73.3269 10.0276 72.9206 9.33816V12.9166H71.4929V3.65235H72.8018L72.9193 4.66772C73.3256 3.97825 74.189 3.5225 75.2366 3.5225C77.017 3.5225 78.4186 4.75861 78.4186 6.9971L78.42 6.9958ZM76.94 6.9958C76.94 5.62985 76.1288 4.78328 74.9492 4.78328C73.8232 4.77029 72.9598 5.62855 72.9598 7.00878C72.9598 8.38901 73.8246 9.18235 74.9492 9.18235C76.0739 9.18235 76.94 8.36304 76.94 6.9958Z"
-            fill="currentColor"
-          ></path>
-          <path
-            d="M86.0132 7.3736H80.8809C80.9071 8.62268 81.7313 9.2732 82.7789 9.2732C83.564 9.2732 84.2197 8.90834 84.494 8.17992H85.9479C85.5939 9.53288 84.3895 10.4444 82.7528 10.4444C80.749 10.4444 79.4271 9.06545 79.4271 6.96978C79.4271 4.87412 80.749 3.50818 82.7397 3.50818C84.7305 3.50818 86.0132 4.83517 86.0132 6.83994V7.3736ZM80.894 6.38419H84.5594C84.481 5.226 83.709 4.6404 82.7397 4.6404C81.7705 4.6404 80.9985 5.226 80.894 6.38419Z"
-            fill="currentColor"
-          ></path>
-          <path
-            d="M88.5407 3.65204C87.8745 3.65204 87.335 4.18829 87.335 4.85048V10.3156H88.7758V5.22703C88.7758 5.06213 88.9104 4.92709 89.0776 4.92709H91.2773V3.65204H88.5407Z"
-            fill="currentColor"
-          ></path>
-          -
-          <path
-            d="M69.1899 3.63908L67.3442 9.17039L65.3535 3.65207H63.8082L66.3606 10.2247C66.439 10.4325 66.4782 10.6026 66.4782 10.7713C66.4782 10.8635 66.469 10.9479 66.4533 11.0258L66.4494 11.0401C66.4403 11.0817 66.4298 11.1206 66.4168 11.1583L66.3201 11.5102C66.2966 11.5971 66.2169 11.6569 66.1268 11.6569H64.0956V12.9189H65.5755C66.5709 12.9189 67.3952 12.6852 67.8667 11.3829L70.6817 3.65207L69.1886 3.63908H69.1899Z"
-            fill="currentColor"
-          ></path>
-          <path
-            d="M57 10.3144H58.4264V6.72299C58.4264 5.60375 59.0417 4.82339 60.1807 4.82339C61.1761 4.81041 61.7913 5.396 61.7913 6.68404V10.3144H63.2191V6.46201C63.2191 4.18457 61.8188 3.50809 60.5478 3.50809C59.5785 3.50809 58.8196 3.88593 58.4264 4.51047V0.919022H57V10.3144Z"
-            fill="currentColor"
-          ></path>
-          <path
-            d="M93.1623 8.29808C93.1753 8.98755 93.8167 9.39136 94.6945 9.39136C95.5723 9.39136 96.0948 9.06545 96.0948 8.47986C96.0948 7.97218 95.8336 7.69951 95.0733 7.58135L93.7253 7.34763C92.4164 7.1269 91.9057 6.44912 91.9057 5.49997C91.9057 4.30282 93.097 3.52246 94.6161 3.52246C96.2529 3.52246 97.4442 4.30282 97.4572 5.63111H96.0439C96.0308 4.95463 95.4417 4.57679 94.6174 4.57679C93.7932 4.57679 93.3347 4.90269 93.3347 5.44933C93.3347 5.93105 93.6756 6.15178 94.4215 6.28162L95.7434 6.51534C96.987 6.73607 97.563 7.34763 97.563 8.35002C97.563 9.72895 96.2803 10.4457 94.722 10.4457C92.9546 10.4457 91.7633 9.60041 91.7372 8.29808H93.1649H93.1623Z"
-            fill="currentColor"
-          ></path>
-          <path
-            d="M100.808 8.75352L102.327 3.652H103.82L105.313 8.75352L106.583 3.652H108.089L106.191 10.3155H104.58L103.061 5.23997L101.529 10.3155H99.9052L97.9941 3.652H99.5002L100.809 8.75352H100.808Z"
-            fill="currentColor"
-          ></path>
-          <path
-            d="M108.926 0.918945H110.511V2.40305H108.926V0.918945ZM109.005 3.65214H110.431V10.3157H109.005V3.65214Z"
-            fill="currentColor"
-          ></path>
-          <path
-            d="M119.504 4.7452C118.391 4.7452 117.632 5.55152 117.632 6.9707C117.632 8.46779 118.417 9.19621 119.465 9.19621C120.302 9.19621 120.919 8.72748 121.193 7.84325H122.712C122.371 9.45719 121.141 10.4466 119.491 10.4466C117.502 10.4466 116.165 9.06767 116.165 6.972C116.165 4.87634 117.5 3.51039 119.504 3.51039C121.141 3.51039 122.358 4.43487 122.712 6.04752H121.167C120.932 5.21523 120.289 4.7465 119.504 4.7465V4.7452Z"
-            fill="currentColor"
-          ></path>
-          <path
-            d="M113.959 9.05208C113.875 9.05208 113.809 8.98456 113.809 8.90276V4.91399H115.367V3.65191H113.809V1.86787H112.382V3.02607C112.382 3.44287 112.252 3.65062 111.833 3.65062H111.256V4.91269H112.382V8.50414C112.382 9.66234 113.024 10.3128 114.189 10.3128H115.354V9.05078H113.96L113.959 9.05208Z"
-            fill="currentColor"
-          ></path>
-          <path
-            d="M127.329 3.50801C126.359 3.50801 125.601 3.88585 125.207 4.5104V0.918945H123.781V10.3144H125.207V6.72292C125.207 5.60367 125.823 4.82332 126.962 4.82332C127.957 4.81033 128.572 5.39592 128.572 6.68397V10.3144H130V6.46193C130 4.18449 128.6 3.50801 127.329 3.50801Z"
-            fill="currentColor"
-          ></path>
-        </g>
+      <svg class="fill-current" height="18" width="130" transform="">
+        <use
+          xlink:href="#hyperswitch-brand"
+          x="0"
+          y="0"
+          height="18"
+          width="130"
+        />
       </svg>
     </div>
-  </body>
 
-  <script>
-    {{ payment_details_js_script }}
-
-    window.state = {
-      prevHeight: window.innerHeight,
-      prevWidth: window.innerWidth,
-      isMobileView: window.innerWidth <= 1200,
-    };
-
-    var widgets = null;
-    const pub_key = window.__PAYMENT_DETAILS.pub_key;
-    const hyper = Hyper(pub_key);
-
-    async function initialize() {
-      const paymentDetails = window.__PAYMENT_DETAILS;
-      var client_secret = paymentDetails.client_secret;
-      const appearance = {
-        variables: {
-          colorPrimary: "rgb(0, 109, 249)",
-          fontFamily: "Work Sans, sans-serif",
-          fontSizeBase: "16px",
-          colorText: "rgb(51, 65, 85)",
-          colorTextSecondary: "#334155B3",
-          colorPrimaryText: "rgb(51, 65, 85)",
-          colorTextPlaceholder: "#33415550",
-          borderColor: "#33415550",
-          colorBackground: "rgb(255, 255, 255)",
-        },
+    <script>
+      {{ payment_details_js_script }}
+
+      window.state = {
+        prevHeight: window.innerHeight,
+        prevWidth: window.innerWidth,
+        isMobileView: window.innerWidth <= 1200,
       };
 
-      widgets = hyper.widgets({
-        appearance,
-        clientSecret: client_secret,
-      });
+      var widgets = null;
+      var unifiedCheckout = null;
+      var pub_key = window.__PAYMENT_DETAILS.pub_key;
+      var hyper = Hyper(pub_key);
+
+      function mountUnifiedCheckout(id) {
+        if (unifiedCheckout !== null) {
+          unifiedCheckout.mount(id);
+        }
+      }
 
-      const unifiedCheckoutOptions = {
-        layout: "tabs",
-        wallets: {
-          walletReturnUrl: paymentDetails.return_url,
-          style: {
-            theme: "dark",
-            type: "default",
-            height: 55,
+      async function initialize() {
+        var paymentDetails = window.__PAYMENT_DETAILS;
+        var client_secret = paymentDetails.client_secret;
+        var appearance = {
+          variables: {
+            colorPrimary: paymentDetails.sdk_theme || "rgb(0, 109, 249)",
+            fontFamily: "Work Sans, sans-serif",
+            fontSizeBase: "16px",
+            colorText: "rgb(51, 65, 85)",
+            colorTextSecondary: "#334155B3",
+            colorPrimaryText: "rgb(51, 65, 85)",
+            colorTextPlaceholder: "#33415550",
+            borderColor: "#33415550",
+            colorBackground: "rgb(255, 255, 255)",
           },
-        },
-      };
+        };
 
-      const unifiedCheckout = widgets.create("payment", unifiedCheckoutOptions);
-      unifiedCheckout.mount("#unified-checkout");
-    }
-    initialize();
-
-    async function handleSubmit(e) {
-      setLoading(true);
-      const paymentDetails = window.__PAYMENT_DETAILS;
-      const { error, data, status } = await hyper.confirmPayment({
-        widgets,
-        confirmParams: {
-          // Make sure to change this to your payment completion page
-          return_url: paymentDetails.return_url,
-        },
-      });
-      // This point will only be reached if there is an immediate error occurring while confirming the payment. Otherwise, your customer will be redirected to your `return_url`.
-      // For some payment flows such as Sofort, iDEAL, your customer will be redirected to an intermediate page to complete authorization of the payment, and then redirected to the `return_url`.
+        widgets = hyper.widgets({
+          appearance,
+          clientSecret: client_secret,
+        });
+
+        var unifiedCheckoutOptions = {
+          layout: "tabs",
+          sdkHandleConfirmPayment: true,
+          branding: "never",
+          wallets: {
+            walletReturnUrl: paymentDetails.return_url,
+            style: {
+              theme: "dark",
+              type: "default",
+              height: 55,
+            },
+          },
+        };
 
-      if (error) {
-        if (error.type === "validation_error") {
-          showMessage(error.message);
+        unifiedCheckout = widgets.create("payment", unifiedCheckoutOptions);
+        mountUnifiedCheckout("#unified-checkout");
+
+        // Handle button press callback
+        var paymentElement = widgets.getElement("payment");
+        if (paymentElement) {
+          paymentElement.on("confirmTriggered", function (event) {
+            handleSubmit(event);
+          });
+        }
+      }
+      initialize();
+
+      async function handleSubmit(e) {
+        var paymentDetails = window.__PAYMENT_DETAILS;
+        var { error, data, status } = await hyper.confirmPayment({
+          widgets,
+          confirmParams: {
+            // Make sure to change this to your payment completion page
+            return_url: paymentDetails.return_url,
+          },
+        });
+        // This point will only be reached if there is an immediate error occurring while confirming the payment. Otherwise, your customer will be redirected to your 'return_url'.
+        // For some payment flows such as Sofort, iDEAL, your customer will be redirected to an intermediate page to complete authorization of the payment, and then redirected to the 'return_url'.
+
+        if (error) {
+          if (error.type === "validation_error") {
+            showMessage(error.message);
+          } else {
+            showMessage("An unexpected error occurred.");
+          }
+
+          // Re-initialize SDK
+          mountUnifiedCheckout("#unified-checkout");
         } else {
-          showMessage("An unexpected error occurred.");
+          var { paymentIntent } = await hyper.retrievePaymentIntent(
+            paymentDetails.client_secret
+          );
+          if (paymentIntent && paymentIntent.status) {
+            hide("#hyper-checkout-sdk");
+            hide("#hyper-checkout-details");
+            show("#hyper-checkout-status");
+            show("#hyper-footer");
+            showStatus(paymentIntent);
+          }
         }
-      } else {
-        const { paymentIntent } = await hyper.retrievePaymentIntent(
-          paymentDetails.client_secret
+      }
+
+      // Fetches the payment status after payment submission
+      async function checkStatus() {
+        var paymentDetails = window.__PAYMENT_DETAILS;
+        var res = {
+          showSdk: true,
+        };
+
+        let clientSecret = new URLSearchParams(window.location.search).get(
+          "payment_intent_client_secret"
         );
-        if (paymentIntent && paymentIntent.status) {
-          hide("#hyper-checkout-sdk");
-          hide("#hyper-checkout-details");
-          show("#hyper-checkout-status");
-          show("#hyper-footer");
-          showStatus(paymentIntent);
+
+        // If clientSecret is not found in URL params, try to fetch from window context
+        if (!clientSecret) {
+          clientSecret = paymentDetails.client_secret;
         }
-      }
 
-      setLoading(false);
-    }
+        // If clientSecret is not present, show status
+        if (!clientSecret) {
+          res.showSdk = false;
+          showStatus(
+            Object.assign({}, paymentDetails, {
+              status: "",
+              error: {
+                code: "NO_CLIENT_SECRET",
+                message: "client_secret not found",
+              },
+            })
+          );
+          return res;
+        }
 
-    // Fetches the payment status after payment submission
-    async function checkStatus() {
-      const clientSecret = new URLSearchParams(window.location.search).get(
-        "payment_intent_client_secret"
-      );
-      const res = {
-        showSdk: true,
-      };
+        var { paymentIntent } = await hyper.retrievePaymentIntent(clientSecret);
+
+        // If paymentIntent was not found, show status
+        if (!paymentIntent) {
+          res.showSdk = false;
+          showStatus(
+            Object.assign({}, paymentDetails, {
+              status: "",
+              error: {
+                code: "NOT_FOUND",
+                message: "PaymentIntent was not found",
+              },
+            })
+          );
+          return res;
+        }
 
-      if (!clientSecret) {
-        return res;
-      }
+        // Show SDK only if paymentIntent status has not been initiated
+        switch (paymentIntent.status) {
+          case "requires_confirmation":
+          case "requires_payment_method":
+            return res;
+        }
 
-      const { paymentIntent } = await hyper.retrievePaymentIntent(clientSecret);
+        showStatus(paymentIntent);
+        res.showSdk = false;
 
-      if (!paymentIntent || !paymentIntent.status) {
         return res;
       }
 
-      showStatus(paymentIntent);
-      res.showSdk = false;
-
-      return res;
-    }
-
-    function setPageLoading(showLoader) {
-      if (showLoader) {
-        show(".page-spinner");
-      } else {
-        hide(".page-spinner");
-      }
-    }
-
-    function setLoading(showLoader) {
-      if (showLoader) {
-        show(".spinner");
-        hide("#button-text");
-      } else {
-        hide(".spinner");
-        show("#button-text");
-      }
-    }
-
-    function show(id) {
-      removeClass(id, "hidden");
-    }
-    function hide(id) {
-      addClass(id, "hidden");
-    }
-
-    function showMessage(msg) {
-      show("#payment-message");
-      addText("#payment-message", msg);
-    }
-    function showStatus(paymentDetails) {
-      const status = paymentDetails.status;
-      let statusDetails = {
-        imageSource: "",
-        message: "",
-        status: status,
-        amountText: "",
-        items: [],
-      };
+      function setPageLoading(showLoader) {
+        if (showLoader) {
+          show(".page-spinner");
+        } else {
+          hide(".page-spinner");
+        }
+      }
 
-      switch (status) {
-        case "succeeded":
-          statusDetails.imageSource =
-            "http://www.clipartbest.com/cliparts/4ib/oRa/4iboRa7RT.png";
-          statusDetails.message = "Payment successful";
-          statusDetails.status = "Succeeded";
-          statusDetails.amountText = new Date(
-            paymentDetails.created
-          ).toTimeString();
-
-          // Payment details
-          var amountNode = createItem(
-            "AMOUNT PAID",
-            paymentDetails.currency + " " + paymentDetails.amount
-          );
-          var paymentId = createItem("PAYMENT ID", paymentDetails.payment_id);
-          // @ts-ignore
-          statusDetails.items.push(amountNode, paymentId);
-          break;
-
-        case "processing":
-          statusDetails.imageSource =
-            "http://www.clipartbest.com/cliparts/4ib/oRa/4iboRa7RT.png";
-          statusDetails.message = "Payment in progress";
-          statusDetails.status = "Processing";
-          // Payment details
-          var amountNode = createItem(
-            "AMOUNT PAID",
-            paymentDetails.currency + " " + paymentDetails.amount
-          );
-          var paymentId = createItem("PAYMENT ID", paymentDetails.payment_id);
-          // @ts-ignore
-          statusDetails.items.push(amountNode, paymentId);
-          break;
-
-        case "failed":
-          statusDetails.imageSource = "";
-          statusDetails.message = "Payment failed";
-          statusDetails.status = "Failed";
-          // Payment details
-          var amountNode = createItem(
-            "AMOUNT PAID",
-            paymentDetails.currency + " " + paymentDetails.amount
-          );
-          var paymentId = createItem("PAYMENT ID", paymentDetails.payment_id);
-          // @ts-ignore
-          statusDetails.items.push(amountNode, paymentId);
-          break;
-
-        case "cancelled":
-          statusDetails.imageSource = "";
-          statusDetails.message = "Payment cancelled";
-          statusDetails.status = "Cancelled";
-          // Payment details
-          var amountNode = createItem(
-            "AMOUNT PAID",
-            paymentDetails.currency + " " + paymentDetails.amount
-          );
-          var paymentId = createItem("PAYMENT ID", paymentDetails.payment_id);
-          // @ts-ignore
-          statusDetails.items.push(amountNode, paymentId);
-          break;
-
-        case "requires_merchant_action":
-          statusDetails.imageSource = "";
-          statusDetails.message = "Payment under review";
-          statusDetails.status = "Under review";
-          // Payment details
-          var amountNode = createItem(
-            "AMOUNT PAID",
-            paymentDetails.currency + " " + paymentDetails.amount
-          );
-          var paymentId = createItem("PAYMENT ID", paymentDetails.payment_id);
-          var paymentId = createItem(
-            "MESSAGE",
-            "Your payment is under review by the merchant."
-          );
-          // @ts-ignore
-          statusDetails.items.push(amountNode, paymentId);
-          break;
-
-        default:
-          statusDetails.imageSource =
-            "http://www.clipartbest.com/cliparts/4ib/oRa/4iboRa7RT.png";
-          statusDetails.message = "Something went wrong";
-          statusDetails.status = "Something went wrong";
-          // Error details
-          if (typeof paymentDetails.error === "object") {
+      function show(id) {
+        removeClass(id, "hidden");
+      }
+      function hide(id) {
+        addClass(id, "hidden");
+      }
+
+      function showMessage(msg) {
+        show("#payment-message");
+        addText("#payment-message", msg);
+      }
+
+      function showStatus(paymentDetails) {
+        var status = paymentDetails.status;
+        let statusDetails = {
+          imageSource: "",
+          message: null,
+          status: status,
+          amountText: "",
+          items: [],
+        };
+
+        // Payment details
+        var paymentId = createItem("Ref Id", paymentDetails.payment_id);
+        // @ts-ignore
+        statusDetails.items.push(paymentId);
+
+        // Status specific information
+        switch (status) {
+          case "succeeded":
+            statusDetails.imageSource = "https://i.imgur.com/5BOmYVl.png";
+            statusDetails.message =
+              "We have successfully received your payment";
+            statusDetails.status = "Paid successfully";
+            statusDetails.amountText = new Date(
+              paymentDetails.created
+            ).toTimeString();
+            break;
+
+          case "processing":
+            statusDetails.imageSource = "https://i.imgur.com/Yb79Qt4.png";
+            statusDetails.message =
+              "Sorry! Your payment is taking longer than expected. Please check back again in sometime.";
+            statusDetails.status = "Payment Pending";
+            break;
+
+          case "failed":
+            statusDetails.imageSource = "https://i.imgur.com/UD8CEuY.png";
+            statusDetails.status = "Payment Failed!";
             var errorCodeNode = createItem(
-              "ERROR CODE",
-              paymentDetails.error.code
+              "Error code",
+              paymentDetails.error_code
             );
             var errorMessageNode = createItem(
-              "ERROR MESSAGE",
-              paymentDetails.error.message
+              "Error message",
+              paymentDetails.error_message
             );
             // @ts-ignore
             statusDetails.items.push(errorMessageNode, errorCodeNode);
+            break;
+
+          case "cancelled":
+            statusDetails.imageSource = "https://i.imgur.com/UD8CEuY.png";
+            statusDetails.status = "Payment Cancelled";
+            break;
+
+          case "requires_merchant_action":
+            statusDetails.imageSource = "https://i.imgur.com/Yb79Qt4.png";
+            statusDetails.status = "Payment under review";
+            break;
+
+          case "requires_capture":
+            statusDetails.imageSource = "https://i.imgur.com/Yb79Qt4.png";
+            statusDetails.status = "Payment Pending";
+            break;
+
+          case "partially_captured":
+            statusDetails.imageSource = "https://i.imgur.com/Yb79Qt4.png";
+            statusDetails.message = "Partial payment was captured.";
+            statusDetails.status = "Partial Payment Pending";
+            break;
+
+          default:
+            statusDetails.imageSource = "https://i.imgur.com/UD8CEuY.png";
+            statusDetails.status = "Something went wrong";
+            // Error details
+            if (typeof paymentDetails.error === "object") {
+              var errorCodeNode = createItem(
+                "Error Code",
+                paymentDetails.error.code
+              );
+              var errorMessageNode = createItem(
+                "Error Message",
+                paymentDetails.error.message
+              );
+              // @ts-ignore
+              statusDetails.items.push(errorMessageNode, errorCodeNode);
+            }
+            break;
+        }
+
+        // Form header items
+        var amountNode = document.createElement("div");
+        amountNode.className = "hyper-checkout-status-amount";
+        amountNode.innerText =
+          paymentDetails.currency + " " + paymentDetails.amount;
+        var merchantLogoNode = document.createElement("img");
+        merchantLogoNode.className = "hyper-checkout-status-merchant-logo";
+        merchantLogoNode.src = window.__PAYMENT_DETAILS.merchant_logo;
+        merchantLogoNode.alt = "";
+
+        // Form content items
+        var statusImageNode = document.createElement("img");
+        statusImageNode.className = "hyper-checkout-status-image";
+        statusImageNode.src = statusDetails.imageSource;
+        var statusTextNode = document.createElement("div");
+        statusTextNode.className = "hyper-checkout-status-text";
+        statusTextNode.innerText = statusDetails.status;
+        var statusMessageNode = document.createElement("div");
+        statusMessageNode.className = "hyper-checkout-status-message";
+        statusMessageNode.innerText = statusDetails.message;
+        var statusDetailsNode = document.createElement("div");
+        statusDetailsNode.className = "hyper-checkout-status-details";
+
+        // Append items
+        statusDetails.items.map((item) => statusDetailsNode?.append(item));
+        var statusHeaderNode = document.getElementById(
+          "hyper-checkout-status-header"
+        );
+        if (statusHeaderNode !== null) {
+          statusHeaderNode.append(amountNode, merchantLogoNode);
+        }
+        var statusContentNode = document.getElementById(
+          "hyper-checkout-status-content"
+        );
+        if (statusContentNode !== null) {
+          statusContentNode.append(statusImageNode, statusTextNode);
+          if (statusDetails.message !== null) {
+            statusContentNode.append(statusMessageNode);
           }
-          break;
+          statusContentNode.append(statusDetailsNode);
+        }
       }
 
-      // Append status
-      var statusTextNode = document.getElementById("status-text");
-      if (statusTextNode !== null) {
-        statusTextNode.innerText = statusDetails.message;
+      function createItem(heading, value) {
+        var itemNode = document.createElement("div");
+        itemNode.className = "hyper-checkout-status-item";
+        var headerNode = document.createElement("div");
+        headerNode.className = "hyper-checkout-item-header";
+        headerNode.innerText = heading;
+        var valueNode = document.createElement("div");
+        valueNode.className = "hyper-checkout-item-value";
+        valueNode.innerText = value;
+        itemNode.append(headerNode);
+        itemNode.append(valueNode);
+        return itemNode;
       }
 
-      // Append image
-      var statusImageNode = document.getElementById("status-img");
-      if (statusImageNode !== null) {
-        statusImageNode.src = statusDetails.imageSource;
+      function addText(id, msg) {
+        var element = document.querySelector(id);
+        element.innerText = msg;
       }
 
-      // Append status details
-      var statusDateNode = document.getElementById("status-date");
-      if (statusDateNode !== null) {
-        statusDateNode.innerText = statusDetails.amountText;
-      }
-
-      // Append items
-      var statusItemNode = document.getElementById(
-        "hyper-checkout-status-items"
-      );
-      if (statusItemNode !== null) {
-        statusDetails.items.map((item) => statusItemNode?.append(item));
-      }
-    }
-
-    function createItem(heading, value) {
-      var itemNode = document.createElement("div");
-      itemNode.className = "hyper-checkout-item";
-      var headerNode = document.createElement("div");
-      headerNode.className = "hyper-checkout-item-header";
-      headerNode.innerText = heading;
-      var valueNode = document.createElement("div");
-      valueNode.className = "hyper-checkout-item-value";
-      valueNode.innerText = value;
-      itemNode.append(headerNode);
-      itemNode.append(valueNode);
-      return itemNode;
-    }
-
-    function addText(id, msg) {
-      var element = document.querySelector(id);
-      element.innerText = msg;
-    }
-
-    function addClass(id, className) {
-      var element = document.querySelector(id);
-      element.classList.add(className);
-    }
-
-    function removeClass(id, className) {
-      var element = document.querySelector(id);
-      element.classList.remove(className);
-    }
-
-    function renderPaymentDetails() {
-      const paymentDetails = window.__PAYMENT_DETAILS;
-
-      // Create price node
-      var priceNode = document.createElement("div");
-      priceNode.className = "hyper-checkout-payment-price";
-      priceNode.innerText =
-        paymentDetails.currency + " " + paymentDetails.amount;
-
-      // Create merchant name's node
-      var merchantNameNode = document.createElement("div");
-      merchantNameNode.className = "hyper-checkout-payment-merchant-name";
-      merchantNameNode.innerText =
-        "Requested by " + paymentDetails.merchant_name;
-
-      // Create payment ID node
-      var paymentIdNode = document.createElement("div");
-      paymentIdNode.className = "hyper-checkout-payment-ref";
-      paymentIdNode.innerText = "Ref Id: " + paymentDetails.payment_id;
-
-      // Create merchant logo's node
-      var merchantLogoNode = document.createElement("img");
-      merchantLogoNode.src = paymentDetails.merchant_logo;
-
-      // Create expiry node
-      var paymentExpiryNode = document.createElement("div");
-      paymentExpiryNode.className = "hyper-checkout-payment-footer-expiry";
-      paymentExpiryNode.innerText =
-        "Link expires on: " + new Date(paymentDetails.expiry).toTimeString();
-
-      // Append information to DOM
-      var paymentContextNode = document.getElementById(
-        "hyper-checkout-payment-context"
-      );
-      paymentContextNode.prepend(priceNode);
-      var paymentMerchantDetails = document.getElementById(
-        "hyper-checkout-payment-merchant-details"
-      );
-      paymentMerchantDetails.append(merchantNameNode);
-      paymentMerchantDetails.append(paymentIdNode);
-      var merchantImageNode = document.getElementById(
-        "hyper-checkout-merchant-image"
-      );
-      merchantImageNode.prepend(merchantLogoNode);
-      var footerNode = document.getElementById("hyper-checkout-payment-footer");
-      footerNode.append(paymentExpiryNode);
-    }
-
-    function renderCart() {
-      const paymentDetails = window.__PAYMENT_DETAILS;
-      const orderDetails = paymentDetails.order_details;
-      var cartNode = document.getElementById("hyper-checkout-cart");
-      var cartItemsNode = document.getElementById("hyper-checkout-cart-items");
-
-      const MAX_ITEMS_VISIBLE_AFTER_COLLAPSE =
-        paymentDetails.max_items_visible_after_collapse;
-
-      // Cart items
-      if (Array.isArray(orderDetails)) {
-        orderDetails.map((item, index) => {
-          if (index >= MAX_ITEMS_VISIBLE_AFTER_COLLAPSE) {
-            return;
-          }
-          renderCartItem(
-            item,
-            paymentDetails,
-            index !== 0 && index < MAX_ITEMS_VISIBLE_AFTER_COLLAPSE,
-            cartItemsNode
-          );
-        });
+      function addClass(id, className) {
+        var element = document.querySelector(id);
+        element.classList.add(className);
       }
 
-      // Expand / collapse button
-      const totalItems = orderDetails.length;
-      if (totalItems > MAX_ITEMS_VISIBLE_AFTER_COLLAPSE) {
-        var expandButtonNode = document.createElement("div");
-        expandButtonNode.className = "hyper-checkout-cart-button";
-        expandButtonNode.onclick = handleCartView;
-        var buttonImageNode = document.createElement("img");
-        var buttonTextNode = document.createElement("span");
-        buttonTextNode.id = "hyper-checkout-cart-button-text";
-        const hiddenItemsCount =
-          orderDetails.length - MAX_ITEMS_VISIBLE_AFTER_COLLAPSE;
-        buttonTextNode.innerText = `Show More (${hiddenItemsCount})`;
-        expandButtonNode.append(buttonTextNode, buttonImageNode);
-        cartNode.append(expandButtonNode);
-      }
-    }
-
-    function renderCartItem(
-      item,
-      paymentDetails,
-      shouldAddDividerNode,
-      cartItemsNode
-    ) {
-      // Wrappers
-      var itemWrapperNode = document.createElement("div");
-      itemWrapperNode.className = "hyper-checkout-cart-item";
-      var nameAndQuantityWrapperNode = document.createElement("div");
-      nameAndQuantityWrapperNode.className =
-        "hyper-checkout-cart-product-details";
-      // Image
-      var productImageNode = document.createElement("img");
-      productImageNode.className = "hyper-checkout-cart-product-image";
-      productImageNode.src = item.product_img_link;
-      // Product title
-      var productNameNode = document.createElement("div");
-      productNameNode.className = "hyper-checkout-card-item-name";
-      productNameNode.innerText = item.product_name;
-      // Product quantity
-      var quantityNode = document.createElement("div");
-      quantityNode.className = "hyper-checkout-card-item-quantity";
-      quantityNode.innerText = "Qty: " + item.quantity;
-      // Product price
-      var priceNode = document.createElement("div");
-      priceNode.className = "hyper-checkout-card-item-price";
-      priceNode.innerText = paymentDetails.currency + " " + item.amount;
-      // Append items
-      nameAndQuantityWrapperNode.append(productNameNode, quantityNode);
-      itemWrapperNode.append(
-        productImageNode,
-        nameAndQuantityWrapperNode,
-        priceNode
-      );
-      if (shouldAddDividerNode) {
-        var dividerNode = document.createElement("div");
-        dividerNode.className = "hyper-checkout-cart-item-divider";
-        cartItemsNode.append(dividerNode);
-      }
-      cartItemsNode.append(itemWrapperNode);
-    }
-
-    function handleCartView() {
-      const paymentDetails = window.__PAYMENT_DETAILS;
-      const orderDetails = paymentDetails.order_details;
-      const MAX_ITEMS_VISIBLE_AFTER_COLLAPSE =
-        paymentDetails.max_items_visible_after_collapse;
-      var itemsHTMLCollection = document.getElementsByClassName(
-        "hyper-checkout-cart-item"
-      );
-      var dividerHTMLCollection = document.getElementsByClassName(
-        "hyper-checkout-cart-item-divider"
-      );
-      var cartItems = [].slice.call(itemsHTMLCollection);
-      var dividerItems = [].slice.call(dividerHTMLCollection);
-      var isHidden = cartItems.length < orderDetails.length;
-      var cartItemsNode = document.getElementById("hyper-checkout-cart-items");
-      var cartButtonTextNode = document.getElementById(
-        "hyper-checkout-cart-button-text"
-      );
-      if (isHidden) {
+      function removeClass(id, className) {
+        var element = document.querySelector(id);
+        element.classList.remove(className);
+      }
+
+      function renderPaymentDetails() {
+        var paymentDetails = window.__PAYMENT_DETAILS;
+
+        // Create price node
+        var priceNode = document.createElement("div");
+        priceNode.className = "hyper-checkout-payment-price";
+        priceNode.innerText =
+          paymentDetails.currency + " " + paymentDetails.amount;
+
+        // Create merchant name's node
+        var merchantNameNode = document.createElement("div");
+        merchantNameNode.className = "hyper-checkout-payment-merchant-name";
+        merchantNameNode.innerText =
+          "Requested by " + paymentDetails.merchant_name;
+
+        // Create payment ID node
+        var paymentIdNode = document.createElement("div");
+        paymentIdNode.className = "hyper-checkout-payment-ref";
+        paymentIdNode.innerText = "Ref Id: " + paymentDetails.payment_id;
+
+        // Create merchant logo's node
+        var merchantLogoNode = document.createElement("img");
+        merchantLogoNode.src = paymentDetails.merchant_logo;
+
+        // Create expiry node
+        var paymentExpiryNode = document.createElement("div");
+        paymentExpiryNode.className = "hyper-checkout-payment-footer-expiry";
+        paymentExpiryNode.innerText =
+          "Link expires on: " + new Date(paymentDetails.expiry).toTimeString();
+
+        // Append information to DOM
+        var paymentContextNode = document.getElementById(
+          "hyper-checkout-payment-context"
+        );
+        paymentContextNode.prepend(priceNode);
+        var paymentMerchantDetails = document.getElementById(
+          "hyper-checkout-payment-merchant-details"
+        );
+        paymentMerchantDetails.append(merchantNameNode);
+        paymentMerchantDetails.append(paymentIdNode);
+        var merchantImageNode = document.getElementById(
+          "hyper-checkout-merchant-image"
+        );
+        merchantImageNode.prepend(merchantLogoNode);
+        var footerNode = document.getElementById(
+          "hyper-checkout-payment-footer"
+        );
+        footerNode.append(paymentExpiryNode);
+      }
+
+      function renderCart() {
+        var paymentDetails = window.__PAYMENT_DETAILS;
+        var orderDetails = paymentDetails.order_details;
+        var cartNode = document.getElementById("hyper-checkout-cart");
+        var cartItemsNode = document.getElementById(
+          "hyper-checkout-cart-items"
+        );
+
+        var MAX_ITEMS_VISIBLE_AFTER_COLLAPSE =
+          paymentDetails.max_items_visible_after_collapse;
+
+        // Cart items
         if (Array.isArray(orderDetails)) {
           orderDetails.map((item, index) => {
-            if (index < MAX_ITEMS_VISIBLE_AFTER_COLLAPSE) {
+            if (index >= MAX_ITEMS_VISIBLE_AFTER_COLLAPSE) {
               return;
             }
             renderCartItem(
               item,
               paymentDetails,
-              index >= MAX_ITEMS_VISIBLE_AFTER_COLLAPSE,
+              index !== 0 && index < MAX_ITEMS_VISIBLE_AFTER_COLLAPSE,
               cartItemsNode
             );
           });
         }
-        cartItemsNode.style.maxHeight = cartItemsNode.scrollHeight + "px";
-        cartItemsNode.style.height = cartItemsNode.scrollHeight + "px";
-        cartButtonTextNode.innerText = "Show Less";
-      } else {
-        cartItemsNode.style.maxHeight = "354px";
-        cartItemsNode.style.height = "354px";
-        cartItemsNode.scrollTo({ top: 0, behavior: "smooth" });
-        setTimeout(() => {
-          cartItems.map((item, index) => {
-            if (index < MAX_ITEMS_VISIBLE_AFTER_COLLAPSE) {
-              return;
-            }
-            cartItemsNode.removeChild(item);
-          });
-          dividerItems.map((item, index) => {
-            if (index < MAX_ITEMS_VISIBLE_AFTER_COLLAPSE - 1) {
-              return;
-            }
-            cartItemsNode.removeChild(item);
-          });
-        }, 300);
-        setTimeout(() => {
-          const hiddenItemsCount =
+
+        // Expand / collapse button
+        var totalItems = orderDetails.length;
+        if (totalItems > MAX_ITEMS_VISIBLE_AFTER_COLLAPSE) {
+          var expandButtonNode = document.createElement("div");
+          expandButtonNode.className = "hyper-checkout-cart-button";
+          expandButtonNode.onclick = handleCartView;
+          var buttonImageNode = document.createElement("img");
+          var buttonTextNode = document.createElement("span");
+          buttonTextNode.id = "hyper-checkout-cart-button-text";
+          var hiddenItemsCount =
             orderDetails.length - MAX_ITEMS_VISIBLE_AFTER_COLLAPSE;
-          cartButtonTextNode.innerText = `Show More (${hiddenItemsCount})`;
-        }, 250);
-      }
-    }
-
-    function hideCartInMobileView() {
-      window.history.back();
-      const cartNode = document.getElementById("hyper-checkout-cart");
-      cartNode.style.animation = "slide-to-right 0.3s linear";
-      cartNode.style.right = "-582px";
-      setTimeout(() => {
-        hide("#hyper-checkout-cart");
-      }, 300);
-    }
-
-    function viewCartInMobileView() {
-      window.history.pushState("view-cart", "");
-      const cartNode = document.getElementById("hyper-checkout-cart");
-      cartNode.style.animation = "slide-from-right 0.3s linear";
-      cartNode.style.right = "0px";
-      show("#hyper-checkout-cart");
-    }
-
-    function hideCartInMobileView() {
-      window.history.back();
-      hide("#hyper-checkout-cart");
-    }
-
-    function viewCartInMobileView() {
-      show("#hyper-checkout-cart");
-      window.history.pushState("view-cart", "");
-    }
-
-    function renderSDKHeader() {
-      const paymentDetails = window.__PAYMENT_DETAILS;
-
-      // SDK headers' items
-      var sdkHeaderItemNode = document.createElement("div");
-      sdkHeaderItemNode.className = "hyper-checkout-sdk-items";
-      var sdkHeaderMerchantNameNode = document.createElement("div");
-      sdkHeaderMerchantNameNode.className =
-        "hyper-checkout-sdk-header-brand-name";
-      sdkHeaderMerchantNameNode.innerText = paymentDetails.merchant_name;
-      var sdkHeaderAmountNode = document.createElement("div");
-      sdkHeaderAmountNode.className = "hyper-checkout-sdk-header-amount";
-      sdkHeaderAmountNode.innerText =
-        paymentDetails.currency + " " + paymentDetails.amount;
-      sdkHeaderItemNode.append(sdkHeaderMerchantNameNode);
-      sdkHeaderItemNode.append(sdkHeaderAmountNode);
-
-      // Append to SDK header's node
-      var sdkHeaderNode = document.getElementById("hyper-checkout-sdk-header");
-      if (sdkHeaderNode !== null) {
-        sdkHeaderNode.append(sdkHeaderLogoNode);
-        sdkHeaderNode.append(sdkHeaderItemNode);
-      }
-    }
-
-    function showSDK(e) {
-      if (window.state.isMobileView) {
-        hide("#hyper-checkout-cart");
-      } else {
-        show("#hyper-checkout-cart");
+          buttonTextNode.innerText = "Show More (" + hiddenItemsCount + ")";
+          expandButtonNode.append(buttonTextNode, buttonImageNode);
+          cartNode.append(expandButtonNode);
+        }
       }
-      setPageLoading(true);
-      checkStatus()
-        .then((res) => {
-          if (res.showSdk) {
-            renderPaymentDetails();
-            renderCart();
-            renderSDKHeader();
-            show("#hyper-checkout-sdk");
-            show("#hyper-checkout-details");
-          } else {
-            show("#hyper-checkout-status");
-            show("#hyper-footer");
+
+      function renderCartItem(
+        item,
+        paymentDetails,
+        shouldAddDividerNode,
+        cartItemsNode
+      ) {
+        // Wrappers
+        var itemWrapperNode = document.createElement("div");
+        itemWrapperNode.className = "hyper-checkout-cart-item";
+        var nameAndQuantityWrapperNode = document.createElement("div");
+        nameAndQuantityWrapperNode.className =
+          "hyper-checkout-cart-product-details";
+        // Image
+        var productImageNode = document.createElement("img");
+        productImageNode.className = "hyper-checkout-cart-product-image";
+        productImageNode.src = item.product_img_link;
+        // Product title
+        var productNameNode = document.createElement("div");
+        productNameNode.className = "hyper-checkout-card-item-name";
+        productNameNode.innerText = item.product_name;
+        // Product quantity
+        var quantityNode = document.createElement("div");
+        quantityNode.className = "hyper-checkout-card-item-quantity";
+        quantityNode.innerText = "Qty: " + item.quantity;
+        // Product price
+        var priceNode = document.createElement("div");
+        priceNode.className = "hyper-checkout-card-item-price";
+        priceNode.innerText = paymentDetails.currency + " " + item.amount;
+        // Append items
+        nameAndQuantityWrapperNode.append(productNameNode, quantityNode);
+        itemWrapperNode.append(
+          productImageNode,
+          nameAndQuantityWrapperNode,
+          priceNode
+        );
+        if (shouldAddDividerNode) {
+          var dividerNode = document.createElement("div");
+          dividerNode.className = "hyper-checkout-cart-item-divider";
+          cartItemsNode.append(dividerNode);
+        }
+        cartItemsNode.append(itemWrapperNode);
+      }
+
+      function handleCartView() {
+        var paymentDetails = window.__PAYMENT_DETAILS;
+        var orderDetails = paymentDetails.order_details;
+        var MAX_ITEMS_VISIBLE_AFTER_COLLAPSE =
+          paymentDetails.max_items_visible_after_collapse;
+        var itemsHTMLCollection = document.getElementsByClassName(
+          "hyper-checkout-cart-item"
+        );
+        var dividerHTMLCollection = document.getElementsByClassName(
+          "hyper-checkout-cart-item-divider"
+        );
+        var cartItems = [].slice.call(itemsHTMLCollection);
+        var dividerItems = [].slice.call(dividerHTMLCollection);
+        var isHidden = cartItems.length < orderDetails.length;
+        var cartItemsNode = document.getElementById(
+          "hyper-checkout-cart-items"
+        );
+        var cartButtonTextNode = document.getElementById(
+          "hyper-checkout-cart-button-text"
+        );
+        if (isHidden) {
+          if (Array.isArray(orderDetails)) {
+            orderDetails.map((item, index) => {
+              if (index < MAX_ITEMS_VISIBLE_AFTER_COLLAPSE) {
+                return;
+              }
+              renderCartItem(
+                item,
+                paymentDetails,
+                index >= MAX_ITEMS_VISIBLE_AFTER_COLLAPSE,
+                cartItemsNode
+              );
+            });
           }
-        })
-        .catch((err) => {})
-        .finally(() => {
-          setPageLoading(false);
-        });
-    }
-
-    window.addEventListener("resize", (event) => {
-      const currentHeight = window.innerHeight;
-      const currentWidth = window.innerWidth;
-      if (currentWidth <= 1200 && window.state.prevWidth > 1200) {
-        hide("#hyper-checkout-cart");
-      } else if (currentWidth > 1200 && window.state.prevWidth <= 1200) {
+          cartItemsNode.style.maxHeight = cartItemsNode.scrollHeight + "px";
+          cartItemsNode.style.height = cartItemsNode.scrollHeight + "px";
+          cartButtonTextNode.innerText = "Show Less";
+        } else {
+          cartItemsNode.style.maxHeight = "354px";
+          cartItemsNode.style.height = "354px";
+          cartItemsNode.scrollTo({ top: 0, behavior: "smooth" });
+          setTimeout(function () {
+            cartItems.map((item, index) => {
+              if (index < MAX_ITEMS_VISIBLE_AFTER_COLLAPSE) {
+                return;
+              }
+              cartItemsNode.removeChild(item);
+            });
+            dividerItems.map((item, index) => {
+              if (index < MAX_ITEMS_VISIBLE_AFTER_COLLAPSE - 1) {
+                return;
+              }
+              cartItemsNode.removeChild(item);
+            });
+          }, 300);
+          setTimeout(function () {
+            var hiddenItemsCount =
+              orderDetails.length - MAX_ITEMS_VISIBLE_AFTER_COLLAPSE;
+            cartButtonTextNode.innerText =
+              "Show More (" + hiddenItemsCount + ")";
+          }, 250);
+        }
+      }
+
+      function hideCartInMobileView() {
+        window.history.back();
+        var cartNode = document.getElementById("hyper-checkout-cart");
+        cartNode.style.animation = "slide-to-right 0.3s linear";
+        cartNode.style.right = "-582px";
+        setTimeout(function () {
+          hide("#hyper-checkout-cart");
+        }, 300);
+      }
+
+      function viewCartInMobileView() {
+        window.history.pushState("view-cart", "");
+        var cartNode = document.getElementById("hyper-checkout-cart");
+        cartNode.style.animation = "slide-from-right 0.3s linear";
+        cartNode.style.right = "0px";
         show("#hyper-checkout-cart");
       }
 
-      window.state.prevHeight = currentHeight;
-      window.state.prevWidth = currentWidth;
-      window.state.isMobileView = currentWidth <= 1200;
-    });
-  </script>
+      function renderSDKHeader() {
+        var paymentDetails = window.__PAYMENT_DETAILS;
+
+        // SDK headers' items
+        var sdkHeaderItemNode = document.createElement("div");
+        sdkHeaderItemNode.className = "hyper-checkout-sdk-items";
+        var sdkHeaderMerchantNameNode = document.createElement("div");
+        sdkHeaderMerchantNameNode.className =
+          "hyper-checkout-sdk-header-brand-name";
+        sdkHeaderMerchantNameNode.innerText = paymentDetails.merchant_name;
+        var sdkHeaderAmountNode = document.createElement("div");
+        sdkHeaderAmountNode.className = "hyper-checkout-sdk-header-amount";
+        sdkHeaderAmountNode.innerText =
+          paymentDetails.currency + " " + paymentDetails.amount;
+        sdkHeaderItemNode.append(sdkHeaderMerchantNameNode);
+        sdkHeaderItemNode.append(sdkHeaderAmountNode);
+
+        // Append to SDK header's node
+        var sdkHeaderNode = document.getElementById(
+          "hyper-checkout-sdk-header"
+        );
+        if (sdkHeaderNode !== null) {
+          sdkHeaderNode.append(sdkHeaderLogoNode);
+          sdkHeaderNode.append(sdkHeaderItemNode);
+        }
+      }
+
+      function showSDK(e) {
+        if (window.state.isMobileView) {
+          hide("#hyper-checkout-cart");
+        } else {
+          show("#hyper-checkout-cart");
+        }
+        setPageLoading(true);
+        checkStatus()
+          .then((res) => {
+            if (res.showSdk) {
+              renderPaymentDetails();
+              renderCart();
+              renderSDKHeader();
+              show("#hyper-checkout-sdk");
+              show("#hyper-checkout-details");
+            } else {
+              hide("#hyper-checkout-sdk");
+              hide("#hyper-checkout-details");
+              show("#hyper-checkout-status");
+              show("#hyper-footer");
+            }
+          })
+          .catch((err) => {})
+          .finally(() => {
+            setPageLoading(false);
+          });
+      }
+
+      window.addEventListener("resize", (event) => {
+        var currentHeight = window.innerHeight;
+        var currentWidth = window.innerWidth;
+        if (currentWidth <= 1200 && window.state.prevWidth > 1200) {
+          hide("#hyper-checkout-cart");
+        } else if (currentWidth > 1200 && window.state.prevWidth <= 1200) {
+          show("#hyper-checkout-cart");
+        }
+
+        window.state.prevHeight = currentHeight;
+        window.state.prevWidth = currentWidth;
+        window.state.isMobileView = currentWidth <= 1200;
+      });
+    </script>
+  </body>
 </html>
diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs
index 422c3fa19881..b19b381af507 100644
--- a/crates/router/src/core/payment_methods.rs
+++ b/crates/router/src/core/payment_methods.rs
@@ -13,7 +13,10 @@ use diesel_models::enums;
 use crate::{
     core::{errors::RouterResult, payments::helpers},
     routes::AppState,
-    types::api::{self, payments},
+    types::{
+        api::{self, payments},
+        domain,
+    },
 };
 
 pub struct Oss;
@@ -25,6 +28,7 @@ pub trait PaymentMethodRetrieve {
         state: &AppState,
         payment_intent: &PaymentIntent,
         payment_attempt: &PaymentAttempt,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(Option<payments::PaymentMethodData>, Option<String>)>;
 }
 
@@ -35,6 +39,7 @@ impl PaymentMethodRetrieve for Oss {
         state: &AppState,
         payment_intent: &PaymentIntent,
         payment_attempt: &PaymentAttempt,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(Option<payments::PaymentMethodData>, Option<String>)> {
         match pm_data {
             pm_opt @ Some(pm @ api::PaymentMethodData::Card(_)) => {
@@ -44,6 +49,7 @@ impl PaymentMethodRetrieve for Oss {
                     payment_intent,
                     enums::PaymentMethod::Card,
                     pm,
+                    merchant_key_store,
                 )
                 .await?;
 
@@ -64,6 +70,7 @@ impl PaymentMethodRetrieve for Oss {
                     payment_intent,
                     enums::PaymentMethod::BankTransfer,
                     pm,
+                    merchant_key_store,
                 )
                 .await?;
 
@@ -76,6 +83,7 @@ impl PaymentMethodRetrieve for Oss {
                     payment_intent,
                     enums::PaymentMethod::Wallet,
                     pm,
+                    merchant_key_store,
                 )
                 .await?;
 
@@ -88,6 +96,7 @@ impl PaymentMethodRetrieve for Oss {
                     payment_intent,
                     enums::PaymentMethod::BankRedirect,
                     pm,
+                    merchant_key_store,
                 )
                 .await?;
 
diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs
index 1c094a5716d6..38ab03ddcb77 100644
--- a/crates/router/src/core/payment_methods/cards.rs
+++ b/crates/router/src/core/payment_methods/cards.rs
@@ -31,7 +31,10 @@ use crate::{
             transformers::{self as payment_methods},
             vault,
         },
-        payments::helpers,
+        payments::{
+            helpers,
+            routing::{self, SessionFlowRoutingInput},
+        },
     },
     db, logger,
     pii::prelude::*,
@@ -42,7 +45,7 @@ use crate::{
     },
     services,
     types::{
-        api::{self, PaymentMethodCreateExt},
+        api::{self, routing as routing_types, PaymentMethodCreateExt},
         domain::{
             self,
             types::{decrypt, encrypt_optional, AsyncLift},
@@ -933,6 +936,137 @@ pub async fn list_payment_methods(
         .await?;
     }
 
+    if let Some((payment_attempt, payment_intent)) =
+        payment_attempt.as_ref().zip(payment_intent.as_ref())
+    {
+        let routing_enabled_pms = HashSet::from([
+            api_enums::PaymentMethod::BankTransfer,
+            api_enums::PaymentMethod::BankDebit,
+            api_enums::PaymentMethod::BankRedirect,
+        ]);
+
+        let routing_enabled_pm_types = HashSet::from([
+            api_enums::PaymentMethodType::GooglePay,
+            api_enums::PaymentMethodType::ApplePay,
+            api_enums::PaymentMethodType::Klarna,
+            api_enums::PaymentMethodType::Paypal,
+        ]);
+
+        let mut chosen = Vec::<api::SessionConnectorData>::new();
+        for intermediate in &response {
+            if routing_enabled_pm_types.contains(&intermediate.payment_method_type)
+                || routing_enabled_pms.contains(&intermediate.payment_method)
+            {
+                let connector_data = api::ConnectorData::get_connector_by_name(
+                    &state.clone().conf.connectors,
+                    &intermediate.connector,
+                    api::GetToken::from(intermediate.payment_method_type),
+                    None,
+                )
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("invalid connector name received")?;
+
+                chosen.push(api::SessionConnectorData {
+                    payment_method_type: intermediate.payment_method_type,
+                    connector: connector_data,
+                    business_sub_label: None,
+                });
+            }
+        }
+        let sfr = SessionFlowRoutingInput {
+            state: &state,
+            country: shipping_address.clone().and_then(|ad| ad.country),
+            key_store: &key_store,
+            merchant_account: &merchant_account,
+            payment_attempt,
+            payment_intent,
+            chosen,
+        };
+        let result = routing::perform_session_flow_routing(sfr)
+            .await
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("error performing session flow routing")?;
+
+        response.retain(|intermediate| {
+            if !routing_enabled_pm_types.contains(&intermediate.payment_method_type)
+                && !routing_enabled_pms.contains(&intermediate.payment_method)
+            {
+                return true;
+            }
+
+            if let Some(choice) = result.get(&intermediate.payment_method_type) {
+                intermediate.connector == choice.connector.connector_name.to_string()
+            } else {
+                false
+            }
+        });
+
+        let mut routing_info: storage::PaymentRoutingInfo = payment_attempt
+            .straight_through_algorithm
+            .clone()
+            .map(|val| val.parse_value("PaymentRoutingInfo"))
+            .transpose()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Invalid PaymentRoutingInfo format found in payment attempt")?
+            .unwrap_or_else(|| storage::PaymentRoutingInfo {
+                algorithm: None,
+                pre_routing_results: None,
+            });
+
+        let mut pre_routing_results: HashMap<
+            api_enums::PaymentMethodType,
+            routing_types::RoutableConnectorChoice,
+        > = HashMap::new();
+
+        for (pm_type, choice) in result {
+            let routable_choice = routing_types::RoutableConnectorChoice {
+                #[cfg(feature = "backwards_compatibility")]
+                choice_kind: routing_types::RoutableChoiceKind::FullStruct,
+                connector: choice
+                    .connector
+                    .connector_name
+                    .to_string()
+                    .parse()
+                    .into_report()
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("")?,
+                #[cfg(feature = "connector_choice_mca_id")]
+                merchant_connector_id: choice.connector.merchant_connector_id,
+                #[cfg(not(feature = "connector_choice_mca_id"))]
+                sub_label: choice.sub_label,
+            };
+
+            pre_routing_results.insert(pm_type, routable_choice);
+        }
+
+        routing_info.pre_routing_results = Some(pre_routing_results);
+
+        let encoded = utils::Encode::<storage::PaymentRoutingInfo>::encode_to_value(&routing_info)
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Unable to serialize payment routing info to value")?;
+
+        let attempt_update = storage::PaymentAttemptUpdate::UpdateTrackers {
+            payment_token: None,
+            connector: None,
+            straight_through_algorithm: Some(encoded),
+            amount_capturable: None,
+            updated_by: merchant_account.storage_scheme.to_string(),
+            merchant_connector_id: None,
+            surcharge_amount: None,
+            tax_amount: None,
+        };
+
+        state
+            .store
+            .update_payment_attempt_with_attempt_id(
+                payment_attempt.clone(),
+                attempt_update,
+                merchant_account.storage_scheme,
+            )
+            .await
+            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
+    }
+
     let req = api_models::payments::PaymentsRequest::foreign_from((
         payment_attempt.as_ref(),
         shipping_address.as_ref(),
@@ -1810,7 +1944,14 @@ pub async fn do_list_customer_pm_fetch_customer_if_not_passed(
 ) -> errors::RouterResponse<api::CustomerPaymentMethodsListResponse> {
     let db = state.store.as_ref();
     if let Some(customer_id) = customer_id {
-        list_customer_payment_method(&state, merchant_account, key_store, None, customer_id).await
+        Box::pin(list_customer_payment_method(
+            &state,
+            merchant_account,
+            key_store,
+            None,
+            customer_id,
+        ))
+        .await
     } else {
         let cloned_secret = req.and_then(|r| r.client_secret.as_ref().cloned());
         let payment_intent = helpers::verify_payment_intent_time_and_client_secret(
@@ -1823,13 +1964,13 @@ pub async fn do_list_customer_pm_fetch_customer_if_not_passed(
             .as_ref()
             .and_then(|intent| intent.customer_id.to_owned())
             .ok_or(errors::ApiErrorResponse::CustomerNotFound)?;
-        list_customer_payment_method(
+        Box::pin(list_customer_payment_method(
             &state,
             merchant_account,
             key_store,
             payment_intent,
             &customer_id,
-        )
+        ))
         .await
     }
 }
@@ -1877,7 +2018,7 @@ pub async fn list_customer_payment_method(
         let hyperswitch_token = generate_id(consts::ID_LENGTH, "token");
 
         let card = if pm.payment_method == enums::PaymentMethod::Card {
-            get_card_details(&pm, key, state, &hyperswitch_token).await?
+            get_card_details(&pm, key, state, &hyperswitch_token, &key_store).await?
         } else {
             None
         };
@@ -1972,6 +2113,7 @@ async fn get_card_details(
     key: &[u8],
     state: &routes::AppState,
     hyperswitch_token: &str,
+    key_store: &domain::MerchantKeyStore,
 ) -> errors::RouterResult<Option<api::CardDetailFromLocker>> {
     let mut _card_decrypted =
         decrypt::<serde_json::Value, masking::WithType>(pm.payment_method_data.clone(), key)
@@ -1988,7 +2130,7 @@ async fn get_card_details(
             });
 
     Ok(Some(
-        get_lookup_key_from_locker(state, hyperswitch_token, pm).await?,
+        get_lookup_key_from_locker(state, hyperswitch_token, pm, key_store).await?,
     ))
 }
 
@@ -1996,6 +2138,7 @@ pub async fn get_lookup_key_from_locker(
     state: &routes::AppState,
     payment_token: &str,
     pm: &storage::PaymentMethod,
+    merchant_key_store: &domain::MerchantKeyStore,
 ) -> errors::RouterResult<api::CardDetailFromLocker> {
     let card = get_card_from_locker(
         state,
@@ -2016,6 +2159,7 @@ pub async fn get_lookup_key_from_locker(
         payment_token,
         card,
         pm,
+        merchant_key_store,
     )
     .await?;
     Ok(resp)
@@ -2050,6 +2194,7 @@ pub async fn get_lookup_key_for_payout_method(
                 Some(payout_token.to_string()),
                 &pm_parsed,
                 Some(pm.customer_id.to_owned()),
+                key_store,
             )
             .await
             .change_context(errors::ApiErrorResponse::InternalServerError)
@@ -2072,6 +2217,7 @@ impl TempLockerCardSupport {
         payment_token: &str,
         card: api::CardDetailFromLocker,
         pm: &storage::PaymentMethod,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> errors::RouterResult<api::CardDetailFromLocker> {
         let card_number = card.card_number.clone().get_required_value("card_number")?;
         let card_exp_month = card
@@ -2121,8 +2267,14 @@ impl TempLockerCardSupport {
             .change_context(errors::ApiErrorResponse::InternalServerError)
             .attach_printable("Wrapped value2 construction failed when saving card to locker")?;
 
-        let lookup_key =
-            vault::create_tokenize(state, value1, Some(value2), payment_token.to_string()).await?;
+        let lookup_key = vault::create_tokenize(
+            state,
+            value1,
+            Some(value2),
+            payment_token.to_string(),
+            merchant_key_store.key.get_inner(),
+        )
+        .await?;
         vault::add_delete_tokenized_data_task(
             &*state.store,
             &lookup_key,
diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs
index 6e951113547f..086133ec78a5 100644
--- a/crates/router/src/core/payment_methods/transformers.rs
+++ b/crates/router/src/core/payment_methods/transformers.rs
@@ -580,6 +580,21 @@ pub fn get_card_detail(
 }
 
 //------------------------------------------------TokenizeService------------------------------------------------
+pub fn mk_crud_locker_request(
+    locker: &settings::Locker,
+    path: &str,
+    req: api::TokenizePayloadEncrypted,
+) -> CustomResult<services::Request, errors::VaultError> {
+    let body = utils::Encode::<api::TokenizePayloadEncrypted>::encode_to_value(&req)
+        .change_context(errors::VaultError::RequestEncodingFailed)?;
+    let mut url = locker.basilisk_host.to_owned();
+    url.push_str(path);
+    let mut request = services::Request::new(services::Method::Post, &url);
+    request.add_default_headers();
+    request.add_header(headers::CONTENT_TYPE, "application/json".into());
+    request.set_body(body.to_string());
+    Ok(request)
+}
 
 pub fn mk_card_value1(
     card_number: cards::CardNumber,
diff --git a/crates/router/src/core/payment_methods/vault.rs b/crates/router/src/core/payment_methods/vault.rs
index 945745ef38c1..5ad78c9d730e 100644
--- a/crates/router/src/core/payment_methods/vault.rs
+++ b/crates/router/src/core/payment_methods/vault.rs
@@ -4,6 +4,8 @@ use common_utils::{
     generate_id_with_default_len,
 };
 use error_stack::{report, IntoReport, ResultExt};
+#[cfg(feature = "basilisk")]
+use josekit::jwe;
 use masking::PeekInterface;
 use router_env::{instrument, tracing};
 use scheduler::{types::process_data, utils as process_tracker_utils};
@@ -11,21 +13,21 @@ use scheduler::{types::process_data, utils as process_tracker_utils};
 #[cfg(feature = "payouts")]
 use crate::types::api::payouts;
 use crate::{
+    consts,
     core::errors::{self, CustomResult, RouterResult},
     db, logger, routes,
     routes::metrics,
     types::{
-        api,
+        api, domain,
         storage::{self, enums, ProcessTrackerExt},
     },
     utils::{self, StringExt},
 };
-
+#[cfg(feature = "basilisk")]
+use crate::{core::payment_methods::transformers as payment_methods, services, settings};
 const VAULT_SERVICE_NAME: &str = "CARD";
-
-const LOCKER_REDIS_PREFIX: &str = "LOCKER_TOKEN";
-
-const LOCKER_REDIS_EXPIRY_SECONDS: u32 = 60 * 15; // 15 minutes
+#[cfg(feature = "basilisk")]
+const VAULT_VERSION: &str = "0";
 
 pub struct SupplementaryVaultData {
     pub customer_id: Option<String>,
@@ -621,8 +623,10 @@ impl Vault {
     pub async fn get_payment_method_data_from_locker(
         state: &routes::AppState,
         lookup_key: &str,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(Option<api::PaymentMethodData>, SupplementaryVaultData)> {
-        let de_tokenize = get_tokenized_data(state, lookup_key, true).await?;
+        let de_tokenize =
+            get_tokenized_data(state, lookup_key, true, merchant_key_store.key.get_inner()).await?;
         let (payment_method, customer_id) =
             api::PaymentMethodData::from_values(de_tokenize.value1, de_tokenize.value2)
                 .change_context(errors::ApiErrorResponse::InternalServerError)
@@ -638,6 +642,7 @@ impl Vault {
         payment_method: &api::PaymentMethodData,
         customer_id: Option<String>,
         pm: enums::PaymentMethod,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<String> {
         let value1 = payment_method
             .get_value1(customer_id.clone())
@@ -651,7 +656,14 @@ impl Vault {
 
         let lookup_key = token_id.unwrap_or_else(|| generate_id_with_default_len("token"));
 
-        let lookup_key = create_tokenize(state, value1, Some(value2), lookup_key).await?;
+        let lookup_key = create_tokenize(
+            state,
+            value1,
+            Some(value2),
+            lookup_key,
+            merchant_key_store.key.get_inner(),
+        )
+        .await?;
         add_delete_tokenized_data_task(&*state.store, &lookup_key, pm).await?;
         metrics::TOKENIZED_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
         Ok(lookup_key)
@@ -662,8 +674,10 @@ impl Vault {
     pub async fn get_payout_method_data_from_temporary_locker(
         state: &routes::AppState,
         lookup_key: &str,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(Option<api::PayoutMethodData>, SupplementaryVaultData)> {
-        let de_tokenize = get_tokenized_data(state, lookup_key, true).await?;
+        let de_tokenize =
+            get_tokenized_data(state, lookup_key, true, merchant_key_store.key.get_inner()).await?;
         let (payout_method, supp_data) =
             api::PayoutMethodData::from_values(de_tokenize.value1, de_tokenize.value2)
                 .change_context(errors::ApiErrorResponse::InternalServerError)
@@ -679,6 +693,7 @@ impl Vault {
         token_id: Option<String>,
         payout_method: &api::PayoutMethodData,
         customer_id: Option<String>,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<String> {
         let value1 = payout_method
             .get_value1(customer_id.clone())
@@ -692,7 +707,14 @@ impl Vault {
 
         let lookup_key = token_id.unwrap_or_else(|| generate_id_with_default_len("token"));
 
-        let lookup_key = create_tokenize(state, value1, Some(value2), lookup_key).await?;
+        let lookup_key = create_tokenize(
+            state,
+            value1,
+            Some(value2),
+            lookup_key,
+            merchant_key_store.key.get_inner(),
+        )
+        .await?;
         // add_delete_tokenized_data_task(&*state.store, &lookup_key, pm).await?;
         // scheduler_metrics::TOKENIZED_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
         Ok(lookup_key)
@@ -715,28 +737,9 @@ impl Vault {
 
 //------------------------------------------------TokenizeService------------------------------------------------
 
-fn get_redis_temp_locker_encryption_key(state: &routes::AppState) -> RouterResult<Vec<u8>> {
-    #[cfg(feature = "kms")]
-    let secret = state
-        .kms_secrets
-        .redis_temp_locker_encryption_key
-        .peek()
-        .as_bytes()
-        .to_owned();
-
-    #[cfg(not(feature = "kms"))]
-    let secret = hex::decode(
-        state
-            .conf
-            .locker
-            .redis_temp_locker_encryption_key
-            .to_owned(),
-    )
-    .into_report()
-    .change_context(errors::ApiErrorResponse::InternalServerError)
-    .attach_printable("Failed to decode redis temp locker data")?;
-
-    Ok(secret)
+#[inline(always)]
+fn get_redis_locker_key(lookup_key: &str) -> String {
+    format!("{}_{}", consts::LOCKER_REDIS_PREFIX, lookup_key)
 }
 
 #[instrument(skip(state, value1, value2))]
@@ -745,50 +748,69 @@ pub async fn create_tokenize(
     value1: String,
     value2: Option<String>,
     lookup_key: String,
+    encryption_key: &masking::Secret<Vec<u8>>,
 ) -> RouterResult<String> {
-    metrics::CREATED_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
-
-    let redis_key = format!("{}_{}", LOCKER_REDIS_PREFIX, lookup_key);
+    let redis_key = get_redis_locker_key(lookup_key.as_str());
+    let func = || async {
+        metrics::CREATED_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
+
+        let payload_to_be_encrypted = api::TokenizePayloadRequest {
+            value1: value1.clone(),
+            value2: value2.clone().unwrap_or_default(),
+            lookup_key: lookup_key.clone(),
+            service_name: VAULT_SERVICE_NAME.to_string(),
+        };
 
-    let payload_to_be_encrypted = api::TokenizePayloadRequest {
-        value1,
-        value2: value2.unwrap_or_default(),
-        lookup_key: lookup_key.to_owned(),
-        service_name: VAULT_SERVICE_NAME.to_string(),
-    };
+        let payload = utils::Encode::<api::TokenizePayloadRequest>::encode_to_string_of_json(
+            &payload_to_be_encrypted,
+        )
+        .change_context(errors::ApiErrorResponse::InternalServerError)?;
 
-    let payload = utils::Encode::<api::TokenizePayloadRequest>::encode_to_string_of_json(
-        &payload_to_be_encrypted,
-    )
-    .change_context(errors::ApiErrorResponse::InternalServerError)?;
+        let encrypted_payload = GcmAes256
+            .encode_message(encryption_key.peek().as_ref(), payload.as_bytes())
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Failed to encode redis temp locker data")?;
 
-    let secret = get_redis_temp_locker_encryption_key(state)?;
+        let redis_conn = state
+            .store
+            .get_redis_conn()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Failed to get redis connection")?;
+
+        redis_conn
+            .set_key_if_not_exists_with_expiry(
+                redis_key.as_str(),
+                bytes::Bytes::from(encrypted_payload),
+                Some(i64::from(consts::LOCKER_REDIS_EXPIRY_SECONDS)),
+            )
+            .await
+            .map(|_| lookup_key.clone())
+            .map_err(|err| {
+                metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
+                err
+            })
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Error from redis locker")
+    };
 
-    let encrypted_payload = GcmAes256
-        .encode_message(secret.as_ref(), payload.as_bytes())
-        .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("Failed to encode redis temp locker data")?;
+    match func().await {
+        Ok(s) => {
+            logger::info!(
+                "Insert payload in redis locker successful with lookup key: {:?}",
+                redis_key
+            );
+            Ok(s)
+        }
+        Err(err) => {
+            logger::error!("Redis Temp locker Failed: {:?}", err);
 
-    let redis_conn = state
-        .store
-        .get_redis_conn()
-        .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("Failed to get redis connection")?;
+            #[cfg(feature = "basilisk")]
+            return old_create_tokenize(state, value1, value2, lookup_key).await;
 
-    redis_conn
-        .set_key_if_not_exists_with_expiry(
-            redis_key.as_str(),
-            bytes::Bytes::from(encrypted_payload),
-            Some(i64::from(LOCKER_REDIS_EXPIRY_SECONDS)),
-        )
-        .await
-        .map(|_| lookup_key)
-        .map_err(|err| {
-            metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
-            err
-        })
-        .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("Error from redis locker")
+            #[cfg(not(feature = "basilisk"))]
+            Err(err)
+        }
+    }
 }
 
 #[instrument(skip(state))]
@@ -796,70 +818,116 @@ pub async fn get_tokenized_data(
     state: &routes::AppState,
     lookup_key: &str,
     _should_get_value2: bool,
+    encryption_key: &masking::Secret<Vec<u8>>,
 ) -> RouterResult<api::TokenizePayloadRequest> {
-    metrics::GET_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
-
-    let redis_key = format!("{}_{}", LOCKER_REDIS_PREFIX, lookup_key);
-
-    let redis_conn = state
-        .store
-        .get_redis_conn()
-        .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("Failed to get redis connection")?;
-
-    let response = redis_conn.get_key::<bytes::Bytes>(redis_key.as_str()).await;
-
-    match response {
-        Ok(resp) => {
-            let secret = get_redis_temp_locker_encryption_key(state)?;
-
-            let decrypted_payload = GcmAes256
-                .decode_message(secret.as_ref(), masking::Secret::new(resp.into()))
-                .change_context(errors::ApiErrorResponse::InternalServerError)
-                .attach_printable("Failed to decode redis temp locker data")?;
+    let redis_key = get_redis_locker_key(lookup_key);
+    let func = || async {
+        metrics::GET_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
 
-            let get_response: api::TokenizePayloadRequest = bytes::Bytes::from(decrypted_payload)
-                .parse_struct("TokenizePayloadRequest")
-                .change_context(errors::ApiErrorResponse::InternalServerError)
-                .attach_printable("Error getting TokenizePayloadRequest from tokenize response")?;
+        let redis_conn = state
+            .store
+            .get_redis_conn()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Failed to get redis connection")?;
+
+        let response = redis_conn.get_key::<bytes::Bytes>(redis_key.as_str()).await;
+
+        match response {
+            Ok(resp) => {
+                let decrypted_payload = GcmAes256
+                    .decode_message(
+                        encryption_key.peek().as_ref(),
+                        masking::Secret::new(resp.into()),
+                    )
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("Failed to decode redis temp locker data")?;
+
+                let get_response: api::TokenizePayloadRequest =
+                    bytes::Bytes::from(decrypted_payload)
+                        .parse_struct("TokenizePayloadRequest")
+                        .change_context(errors::ApiErrorResponse::InternalServerError)
+                        .attach_printable(
+                            "Error getting TokenizePayloadRequest from tokenize response",
+                        )?;
+
+                Ok(get_response)
+            }
+            Err(err) => {
+                metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
+                Err(err).change_context(errors::ApiErrorResponse::UnprocessableEntity {
+                    message: "Token is invalid or expired".into(),
+                })
+            }
+        }
+    };
 
-            Ok(get_response)
+    match func().await {
+        Ok(s) => {
+            logger::info!(
+                "Fetch payload in redis locker successful with lookup key: {:?}",
+                redis_key
+            );
+            Ok(s)
         }
         Err(err) => {
-            metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
-            Err(err).change_context(errors::ApiErrorResponse::UnprocessableEntity {
-                message: "Token is invalid or expired".into(),
-            })
+            logger::error!("Redis Temp locker Failed: {:?}", err);
+
+            #[cfg(feature = "basilisk")]
+            return old_get_tokenized_data(state, lookup_key, _should_get_value2).await;
+
+            #[cfg(not(feature = "basilisk"))]
+            Err(err)
         }
     }
 }
 
 #[instrument(skip(state))]
 pub async fn delete_tokenized_data(state: &routes::AppState, lookup_key: &str) -> RouterResult<()> {
-    metrics::DELETED_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
-
-    let redis_key = format!("{}_{}", LOCKER_REDIS_PREFIX, lookup_key);
+    let redis_key = get_redis_locker_key(lookup_key);
+    let func = || async {
+        metrics::DELETED_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
 
-    let redis_conn = state
-        .store
-        .get_redis_conn()
-        .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("Failed to get redis connection")?;
+        let redis_conn = state
+            .store
+            .get_redis_conn()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Failed to get redis connection")?;
 
-    let response = redis_conn.delete_key(redis_key.as_str()).await;
+        let response = redis_conn.delete_key(redis_key.as_str()).await;
 
-    match response {
-        Ok(redis_interface::DelReply::KeyDeleted) => Ok(()),
-        Ok(redis_interface::DelReply::KeyNotDeleted) => {
-            Err(errors::ApiErrorResponse::InternalServerError)
-                .into_report()
-                .attach_printable("Token invalid or expired")
+        match response {
+            Ok(redis_interface::DelReply::KeyDeleted) => Ok(()),
+            Ok(redis_interface::DelReply::KeyNotDeleted) => {
+                Err(errors::ApiErrorResponse::InternalServerError)
+                    .into_report()
+                    .attach_printable("Token invalid or expired")
+            }
+            Err(err) => {
+                metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
+                Err(errors::ApiErrorResponse::InternalServerError)
+                    .into_report()
+                    .attach_printable_lazy(|| {
+                        format!("Failed to delete from redis locker: {err:?}")
+                    })
+            }
+        }
+    };
+    match func().await {
+        Ok(s) => {
+            logger::info!(
+                "Delete payload in redis locker successful with lookup key: {:?}",
+                redis_key
+            );
+            Ok(s)
         }
         Err(err) => {
-            metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
-            Err(errors::ApiErrorResponse::InternalServerError)
-                .into_report()
-                .attach_printable_lazy(|| format!("Failed to delete from redis locker: {err:?}"))
+            logger::error!("Redis Temp locker Failed: {:?}", err);
+
+            #[cfg(feature = "basilisk")]
+            return old_delete_tokenized_data(state, lookup_key).await;
+
+            #[cfg(not(feature = "basilisk"))]
+            Err(err)
         }
     }
 }
@@ -983,3 +1051,248 @@ pub async fn retry_delete_tokenize(
         }
     }
 }
+
+// Fallback logic of old temp locker needs to be removed later
+
+#[cfg(feature = "basilisk")]
+async fn get_locker_jwe_keys(
+    keys: &settings::ActiveKmsSecrets,
+) -> CustomResult<(String, String), errors::EncryptionError> {
+    let keys = keys.jwekey.peek();
+    let key_id = get_key_id(keys);
+    let (public_key, private_key) = if key_id == keys.locker_key_identifier1 {
+        (&keys.locker_encryption_key1, &keys.locker_decryption_key1)
+    } else if key_id == keys.locker_key_identifier2 {
+        (&keys.locker_encryption_key2, &keys.locker_decryption_key2)
+    } else {
+        return Err(errors::EncryptionError.into());
+    };
+
+    Ok((public_key.to_string(), private_key.to_string()))
+}
+
+#[cfg(feature = "basilisk")]
+#[instrument(skip(state, value1, value2))]
+pub async fn old_create_tokenize(
+    state: &routes::AppState,
+    value1: String,
+    value2: Option<String>,
+    lookup_key: String,
+) -> RouterResult<String> {
+    let payload_to_be_encrypted = api::TokenizePayloadRequest {
+        value1,
+        value2: value2.unwrap_or_default(),
+        lookup_key,
+        service_name: VAULT_SERVICE_NAME.to_string(),
+    };
+    let payload = utils::Encode::<api::TokenizePayloadRequest>::encode_to_string_of_json(
+        &payload_to_be_encrypted,
+    )
+    .change_context(errors::ApiErrorResponse::InternalServerError)?;
+
+    let (public_key, private_key) = get_locker_jwe_keys(&state.kms_secrets)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Error getting Encryption key")?;
+    let encrypted_payload = services::encrypt_jwe(payload.as_bytes(), public_key)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Error getting Encrypt JWE response")?;
+
+    let create_tokenize_request = api::TokenizePayloadEncrypted {
+        payload: encrypted_payload,
+        key_id: get_key_id(&state.conf.jwekey).to_string(),
+        version: Some(VAULT_VERSION.to_string()),
+    };
+    let request = payment_methods::mk_crud_locker_request(
+        &state.conf.locker,
+        "/tokenize",
+        create_tokenize_request,
+    )
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Making tokenize request failed")?;
+    let response = services::call_connector_api(state, request)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)?;
+
+    match response {
+        Ok(r) => {
+            let resp: api::TokenizePayloadEncrypted = r
+                .response
+                .parse_struct("TokenizePayloadEncrypted")
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Decoding Failed for TokenizePayloadEncrypted")?;
+            let alg = jwe::RSA_OAEP_256;
+            let decrypted_payload = services::decrypt_jwe(
+                &resp.payload,
+                services::KeyIdCheck::RequestResponseKeyId((
+                    get_key_id(&state.conf.jwekey),
+                    &resp.key_id,
+                )),
+                private_key,
+                alg,
+            )
+            .await
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Decrypt Jwe failed for TokenizePayloadEncrypted")?;
+            let get_response: api::GetTokenizePayloadResponse = decrypted_payload
+                .parse_struct("GetTokenizePayloadResponse")
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable(
+                    "Error getting GetTokenizePayloadResponse from tokenize response",
+                )?;
+            Ok(get_response.lookup_key)
+        }
+        Err(err) => {
+            metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
+            Err(errors::ApiErrorResponse::InternalServerError)
+                .into_report()
+                .attach_printable(format!("Got 4xx from the basilisk locker: {err:?}"))
+        }
+    }
+}
+
+#[cfg(feature = "basilisk")]
+pub async fn old_get_tokenized_data(
+    state: &routes::AppState,
+    lookup_key: &str,
+    should_get_value2: bool,
+) -> RouterResult<api::TokenizePayloadRequest> {
+    metrics::GET_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
+    let payload_to_be_encrypted = api::GetTokenizePayloadRequest {
+        lookup_key: lookup_key.to_string(),
+        get_value2: should_get_value2,
+        service_name: VAULT_SERVICE_NAME.to_string(),
+    };
+    let payload = serde_json::to_string(&payload_to_be_encrypted)
+        .map_err(|_x| errors::ApiErrorResponse::InternalServerError)?;
+
+    let (public_key, private_key) = get_locker_jwe_keys(&state.kms_secrets)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Error getting Encryption key")?;
+    let encrypted_payload = services::encrypt_jwe(payload.as_bytes(), public_key)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Error getting Encrypt JWE response")?;
+    let create_tokenize_request = api::TokenizePayloadEncrypted {
+        payload: encrypted_payload,
+        key_id: get_key_id(&state.conf.jwekey).to_string(),
+        version: Some("0".to_string()),
+    };
+    let request = payment_methods::mk_crud_locker_request(
+        &state.conf.locker,
+        "/tokenize/get",
+        create_tokenize_request,
+    )
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Making Get Tokenized request failed")?;
+    let response = services::call_connector_api(state, request)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)?;
+    match response {
+        Ok(r) => {
+            let resp: api::TokenizePayloadEncrypted = r
+                .response
+                .parse_struct("TokenizePayloadEncrypted")
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Decoding Failed for TokenizePayloadEncrypted")?;
+            let alg = jwe::RSA_OAEP_256;
+            let decrypted_payload = services::decrypt_jwe(
+                &resp.payload,
+                services::KeyIdCheck::RequestResponseKeyId((
+                    get_key_id(&state.conf.jwekey),
+                    &resp.key_id,
+                )),
+                private_key,
+                alg,
+            )
+            .await
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("GetTokenizedApi: Decrypt Jwe failed for TokenizePayloadEncrypted")?;
+            let get_response: api::TokenizePayloadRequest = decrypted_payload
+                .parse_struct("TokenizePayloadRequest")
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Error getting TokenizePayloadRequest from tokenize response")?;
+            Ok(get_response)
+        }
+        Err(err) => {
+            metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
+            match err.status_code {
+                404 => Err(errors::ApiErrorResponse::UnprocessableEntity {
+                    message: "Token is invalid or expired".into(),
+                }
+                .into()),
+                _ => Err(errors::ApiErrorResponse::InternalServerError)
+                    .into_report()
+                    .attach_printable(format!("Got error from the basilisk locker: {err:?}")),
+            }
+        }
+    }
+}
+
+#[cfg(feature = "basilisk")]
+pub async fn old_delete_tokenized_data(
+    state: &routes::AppState,
+    lookup_key: &str,
+) -> RouterResult<()> {
+    metrics::DELETED_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
+    let payload_to_be_encrypted = api::DeleteTokenizeByTokenRequest {
+        lookup_key: lookup_key.to_string(),
+        service_name: VAULT_SERVICE_NAME.to_string(),
+    };
+    let payload = serde_json::to_string(&payload_to_be_encrypted)
+        .into_report()
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Error serializing api::DeleteTokenizeByTokenRequest")?;
+
+    let (public_key, _private_key) = get_locker_jwe_keys(&state.kms_secrets.clone())
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Error getting Encryption key")?;
+    let encrypted_payload = services::encrypt_jwe(payload.as_bytes(), public_key)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Error getting Encrypt JWE response")?;
+    let create_tokenize_request = api::TokenizePayloadEncrypted {
+        payload: encrypted_payload,
+        key_id: get_key_id(&state.conf.jwekey).to_string(),
+        version: Some("0".to_string()),
+    };
+    let request = payment_methods::mk_crud_locker_request(
+        &state.conf.locker,
+        "/tokenize/delete/token",
+        create_tokenize_request,
+    )
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Making Delete Tokenized request failed")?;
+    let response = services::call_connector_api(state, request)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Error while making /tokenize/delete/token call to the locker")?;
+    match response {
+        Ok(r) => {
+            let _delete_response = std::str::from_utf8(&r.response)
+                .into_report()
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Decoding Failed for basilisk delete response")?;
+            Ok(())
+        }
+        Err(err) => {
+            metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
+            Err(errors::ApiErrorResponse::InternalServerError)
+                .into_report()
+                .attach_printable(format!("Got 4xx from the basilisk locker: {err:?}"))
+        }
+    }
+}
+
+#[cfg(feature = "basilisk")]
+pub fn get_key_id(keys: &settings::Jwekey) -> &str {
+    let key_identifier = "1"; // [#46]: Fetch this value from redis or external sources
+    if key_identifier == "1" {
+        &keys.locker_key_identifier1
+    } else {
+        &keys.locker_key_identifier2
+    }
+}
diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs
index 20712a64397d..7e19b0b60571 100644
--- a/crates/router/src/core/payments.rs
+++ b/crates/router/src/core/payments.rs
@@ -3,15 +3,18 @@ pub mod customers;
 pub mod flows;
 pub mod helpers;
 pub mod operations;
+#[cfg(feature = "retry")]
+pub mod retry;
+pub mod routing;
 pub mod tokenization;
 pub mod transformers;
 pub mod types;
 
-use std::{fmt::Debug, marker::PhantomData, ops::Deref, time::Instant};
+use std::{fmt::Debug, marker::PhantomData, ops::Deref, time::Instant, vec::IntoIter};
 
 use api_models::{
     enums,
-    payment_methods::{SurchargeDetailsResponse, SurchargeMetadata},
+    payment_methods::{Surcharge, SurchargeDetailsResponse},
     payments::HeaderPayload,
 };
 use common_utils::{ext_traits::AsyncExt, pii};
@@ -35,6 +38,7 @@ pub use self::operations::{
 use self::{
     flows::{ConstructFlowSpecificData, Feature},
     operations::{payment_complete_authorize, BoxedOperation, Operation},
+    routing::{self as self_routing, SessionFlowRoutingInput},
 };
 use super::errors::StorageErrorExt;
 use crate::{
@@ -49,8 +53,11 @@ use crate::{
     routes::{metrics, payment_methods::ParentPaymentMethodToken, AppState},
     services::{self, api::Authenticate},
     types::{
-        self as router_types, api, domain,
+        self as router_types,
+        api::{self, ConnectorCallType},
+        domain,
         storage::{self, enums as storage_enums},
+        transformers::ForeignTryInto,
     },
     utils::{
         add_apple_pay_flow_metrics, add_connector_http_status_code_metrics, Encode, OptionExt,
@@ -69,6 +76,7 @@ pub async fn payments_operation_core<F, Req, Op, FData, Ctx>(
     req: Req,
     call_connector_action: CallConnectorAction,
     auth_flow: services::AuthFlow,
+    eligible_connectors: Option<Vec<api_models::enums::RoutableConnectors>>,
     header_payload: HeaderPayload,
 ) -> RouterResult<(
     PaymentData<F>,
@@ -136,34 +144,18 @@ where
         &merchant_account,
         &key_store,
         &mut payment_data,
+        eligible_connectors,
     )
     .await?;
 
-    let schedule_time = match &connector {
-        Some(api::ConnectorCallType::Single(connector_data)) => {
-            if should_add_task_to_process_tracker(&payment_data) {
-                payment_sync::get_sync_process_schedule_time(
-                    &*state.store,
-                    connector_data.connector.id(),
-                    &merchant_account.merchant_id,
-                    0,
-                )
-                .await
-                .into_report()
-                .change_context(errors::ApiErrorResponse::InternalServerError)
-                .attach_printable("Failed while getting process schedule time")?
-            } else {
-                None
-            }
-        }
-        _ => None,
-    };
+    let should_add_task_to_process_tracker = should_add_task_to_process_tracker(&payment_data);
 
     payment_data = tokenize_in_router_when_confirm_false(
         state,
         &operation,
         &mut payment_data,
         &validate_result,
+        &key_store,
     )
     .await?;
 
@@ -171,7 +163,21 @@ where
     let mut external_latency = None;
     if let Some(connector_details) = connector {
         payment_data = match connector_details {
-            api::ConnectorCallType::Single(connector) => {
+            api::ConnectorCallType::PreDetermined(connector) => {
+                let schedule_time = if should_add_task_to_process_tracker {
+                    payment_sync::get_sync_process_schedule_time(
+                        &*state.store,
+                        connector.connector.id(),
+                        &merchant_account.merchant_id,
+                        0,
+                    )
+                    .await
+                    .into_report()
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("Failed while getting process schedule time")?
+                } else {
+                    None
+                };
                 let router_data = call_connector_service(
                     state,
                     &merchant_account,
@@ -186,9 +192,86 @@ where
                     header_payload,
                 )
                 .await?;
+                let operation = Box::new(PaymentResponse);
+
+                connector_http_status_code = router_data.connector_http_status_code;
+                external_latency = router_data.external_latency;
+                //add connector http status code metrics
+                add_connector_http_status_code_metrics(connector_http_status_code);
+                operation
+                    .to_post_update_tracker()?
+                    .update_tracker(
+                        state,
+                        &validate_result.payment_id,
+                        payment_data,
+                        router_data,
+                        merchant_account.storage_scheme,
+                    )
+                    .await?
+            }
+
+            api::ConnectorCallType::Retryable(connectors) => {
+                let mut connectors = connectors.into_iter();
+
+                let connector_data = get_connector_data(&mut connectors)?;
+
+                let schedule_time = if should_add_task_to_process_tracker {
+                    payment_sync::get_sync_process_schedule_time(
+                        &*state.store,
+                        connector_data.connector.id(),
+                        &merchant_account.merchant_id,
+                        0,
+                    )
+                    .await
+                    .into_report()
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("Failed while getting process schedule time")?
+                } else {
+                    None
+                };
+                let router_data = call_connector_service(
+                    state,
+                    &merchant_account,
+                    &key_store,
+                    connector_data.clone(),
+                    &operation,
+                    &mut payment_data,
+                    &customer,
+                    call_connector_action,
+                    &validate_result,
+                    schedule_time,
+                    header_payload,
+                )
+                .await?;
+
+                #[cfg(feature = "retry")]
+                let mut router_data = router_data;
+                #[cfg(feature = "retry")]
+                {
+                    use crate::core::payments::retry::{self, GsmValidation};
+                    let config_bool =
+                        retry::config_should_call_gsm(&*state.store, &merchant_account.merchant_id)
+                            .await;
+
+                    if config_bool && router_data.should_call_gsm() {
+                        router_data = retry::do_gsm_actions(
+                            state,
+                            &mut payment_data,
+                            connectors,
+                            connector_data,
+                            router_data,
+                            &merchant_account,
+                            &key_store,
+                            &operation,
+                            &customer,
+                            &validate_result,
+                            schedule_time,
+                        )
+                        .await?;
+                    };
+                }
 
                 let operation = Box::new(PaymentResponse);
-                let db = &*state.store;
                 connector_http_status_code = router_data.connector_http_status_code;
                 external_latency = router_data.external_latency;
                 //add connector http status code metrics
@@ -196,7 +279,7 @@ where
                 operation
                     .to_post_update_tracker()?
                     .update_tracker(
-                        db,
+                        state,
                         &validate_result.payment_id,
                         payment_data,
                         router_data,
@@ -205,7 +288,9 @@ where
                     .await?
             }
 
-            api::ConnectorCallType::Multiple(connectors) => {
+            api::ConnectorCallType::SessionMultiple(connectors) => {
+                let session_surcharge_data =
+                    get_session_surcharge_data(&payment_data.payment_attempt);
                 call_multiple_connectors_service(
                     state,
                     &merchant_account,
@@ -214,6 +299,7 @@ where
                     &operation,
                     payment_data,
                     &customer,
+                    session_surcharge_data,
                 )
                 .await?
             }
@@ -236,7 +322,7 @@ where
         (_, payment_data) = operation
             .to_update_tracker()?
             .update_trackers(
-                &*state.store,
+                state,
                 payment_data.clone(),
                 customer.clone(),
                 validate_result.storage_scheme,
@@ -257,6 +343,32 @@ where
     ))
 }
 
+#[inline]
+pub fn get_connector_data(
+    connectors: &mut IntoIter<api::ConnectorData>,
+) -> RouterResult<api::ConnectorData> {
+    connectors
+        .next()
+        .ok_or(errors::ApiErrorResponse::InternalServerError)
+        .into_report()
+        .attach_printable("Connector not found in connectors iterator")
+}
+
+pub fn get_session_surcharge_data(
+    payment_attempt: &data_models::payments::payment_attempt::PaymentAttempt,
+) -> Option<api::SessionSurchargeDetails> {
+    payment_attempt.surcharge_amount.map(|surcharge_amount| {
+        let tax_on_surcharge_amount = payment_attempt.tax_amount.unwrap_or(0);
+        let final_amount = payment_attempt.amount + surcharge_amount + tax_on_surcharge_amount;
+        api::SessionSurchargeDetails::PreDetermined(SurchargeDetailsResponse {
+            surcharge: Surcharge::Fixed(surcharge_amount),
+            tax_on_surcharge: None,
+            surcharge_amount,
+            tax_on_surcharge_amount,
+            final_amount,
+        })
+    })
+}
 #[allow(clippy::too_many_arguments)]
 pub async fn payments_core<F, Res, Req, Op, FData, Ctx>(
     state: AppState,
@@ -266,6 +378,7 @@ pub async fn payments_core<F, Res, Req, Op, FData, Ctx>(
     req: Req,
     auth_flow: services::AuthFlow,
     call_connector_action: CallConnectorAction,
+    eligible_connectors: Option<Vec<api_models::enums::Connector>>,
     header_payload: HeaderPayload,
 ) -> RouterResponse<Res>
 where
@@ -286,6 +399,12 @@ where
     // To perform router related operation for PaymentResponse
     PaymentResponse: Operation<F, FData, Ctx>,
 {
+    let eligible_routable_connectors = eligible_connectors.map(|connectors| {
+        connectors
+            .into_iter()
+            .flat_map(|c| c.foreign_try_into())
+            .collect()
+    });
     let (payment_data, req, customer, connector_http_status_code, external_latency) =
         payments_operation_core::<_, _, _, _, Ctx>(
             &state,
@@ -295,6 +414,7 @@ where
             req,
             call_connector_action,
             auth_flow,
+            eligible_routable_connectors,
             header_payload,
         )
         .await?;
@@ -317,7 +437,7 @@ fn is_start_pay<Op: Debug>(operation: &Op) -> bool {
     format!("{operation:?}").eq("PaymentStart")
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, serde::Serialize)]
 pub struct PaymentsRedirectResponseData {
     pub connector: Option<String>,
     pub param: Option<String>,
@@ -344,7 +464,7 @@ pub trait PaymentRedirectFlow<Ctx: PaymentMethodRetrieve>: Sync {
     fn generate_response(
         &self,
         payments_response: api_models::payments::PaymentsResponse,
-        merchant_account: router_types::domain::MerchantAccount,
+        business_profile: diesel_models::business_profile::BusinessProfile,
         payment_id: String,
         connector: String,
     ) -> RouterResult<api::RedirectionResponse>;
@@ -380,10 +500,13 @@ pub trait PaymentRedirectFlow<Ctx: PaymentMethodRetrieve>: Sync {
                 field_name: "payment_id",
             })?;
 
+        // This connector data is ephemeral, the call payment flow will get new connector data
+        // with merchant account details, so the connector_id can be safely set to None here
         let connector_data = api::ConnectorData::get_connector_by_name(
             &state.conf.connectors,
             &connector,
             api::GetToken::Connector,
+            None,
         )?;
 
         let flow_type = connector_data
@@ -414,8 +537,21 @@ pub trait PaymentRedirectFlow<Ctx: PaymentMethodRetrieve>: Sync {
                 .attach_printable("Failed to get the response in json"),
         }?;
 
+        let profile_id = payments_response
+            .profile_id
+            .as_ref()
+            .get_required_value("profile_id")?;
+
+        let business_profile = state
+            .store
+            .find_business_profile_by_profile_id(profile_id)
+            .await
+            .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound {
+                id: profile_id.to_string(),
+            })?;
+
         let result =
-            self.generate_response(payments_response, merchant_account, resource_id, connector)?;
+            self.generate_response(payments_response, business_profile, resource_id, connector)?;
 
         Ok(services::ApplicationResponse::JsonForRedirection(result))
     }
@@ -445,7 +581,14 @@ impl<Ctx: PaymentMethodRetrieve> PaymentRedirectFlow<Ctx> for PaymentRedirectCom
             }),
             ..Default::default()
         };
-        payments_core::<api::CompleteAuthorize, api::PaymentsResponse, _, _, _, Ctx>(
+        Box::pin(payments_core::<
+            api::CompleteAuthorize,
+            api::PaymentsResponse,
+            _,
+            _,
+            _,
+            Ctx,
+        >(
             state.clone(),
             merchant_account,
             merchant_key_store,
@@ -453,8 +596,9 @@ impl<Ctx: PaymentMethodRetrieve> PaymentRedirectFlow<Ctx> for PaymentRedirectCom
             payment_confirm_req,
             services::api::AuthFlow::Merchant,
             connector_action,
+            None,
             HeaderPayload::default(),
-        )
+        ))
         .await
     }
 
@@ -465,7 +609,7 @@ impl<Ctx: PaymentMethodRetrieve> PaymentRedirectFlow<Ctx> for PaymentRedirectCom
     fn generate_response(
         &self,
         payments_response: api_models::payments::PaymentsResponse,
-        merchant_account: router_types::domain::MerchantAccount,
+        business_profile: diesel_models::business_profile::BusinessProfile,
         payment_id: String,
         connector: String,
     ) -> RouterResult<api::RedirectionResponse> {
@@ -502,7 +646,7 @@ impl<Ctx: PaymentMethodRetrieve> PaymentRedirectFlow<Ctx> for PaymentRedirectCom
             | api_models::enums::IntentStatus::Failed
             | api_models::enums::IntentStatus::Cancelled | api_models::enums::IntentStatus::RequiresCapture| api_models::enums::IntentStatus::Processing=> helpers::get_handle_response_url(
                 payment_id,
-                &merchant_account,
+                &business_profile,
                 payments_response,
                 connector,
             ),
@@ -540,7 +684,14 @@ impl<Ctx: PaymentMethodRetrieve> PaymentRedirectFlow<Ctx> for PaymentRedirectSyn
             expand_attempts: None,
             expand_captures: None,
         };
-        payments_core::<api::PSync, api::PaymentsResponse, _, _, _, Ctx>(
+        Box::pin(payments_core::<
+            api::PSync,
+            api::PaymentsResponse,
+            _,
+            _,
+            _,
+            Ctx,
+        >(
             state.clone(),
             merchant_account,
             merchant_key_store,
@@ -548,21 +699,21 @@ impl<Ctx: PaymentMethodRetrieve> PaymentRedirectFlow<Ctx> for PaymentRedirectSyn
             payment_sync_req,
             services::api::AuthFlow::Merchant,
             connector_action,
+            None,
             HeaderPayload::default(),
-        )
+        ))
         .await
     }
-
     fn generate_response(
         &self,
         payments_response: api_models::payments::PaymentsResponse,
-        merchant_account: router_types::domain::MerchantAccount,
+        business_profile: diesel_models::business_profile::BusinessProfile,
         payment_id: String,
         connector: String,
     ) -> RouterResult<api::RedirectionResponse> {
         helpers::get_handle_response_url(
             payment_id,
-            &merchant_account,
+            &business_profile,
             payments_response,
             connector,
         )
@@ -604,30 +755,29 @@ where
 {
     let stime_connector = Instant::now();
 
-    let pm_data = payment_data.clone();
-
-    let connector_name = pm_data
-        .payment_attempt
-        .connector
-        .as_ref()
-        .get_required_value("connector")?;
-
     let merchant_connector_account = construct_profile_id_and_get_mca(
         state,
         merchant_account,
         payment_data,
-        connector_name,
+        &connector.connector_name.to_string(),
+        connector.merchant_connector_id.as_ref(),
         key_store,
         false,
     )
     .await?;
 
+    if payment_data.payment_attempt.merchant_connector_id.is_none() {
+        payment_data.payment_attempt.merchant_connector_id =
+            merchant_connector_account.get_mca_id();
+    }
+
     let (pd, tokenization_action) = get_connector_tokenization_action_when_confirm_true(
         state,
         operation,
         payment_data,
         validate_result,
         &merchant_connector_account,
+        key_store,
     )
     .await?;
 
@@ -752,7 +902,7 @@ where
     (_, *payment_data) = operation
         .to_update_tracker()?
         .update_trackers(
-            &*state.store,
+            state,
             payment_data.clone(),
             customer.clone(),
             merchant_account.storage_scheme,
@@ -791,6 +941,7 @@ where
     router_data_res
 }
 
+#[allow(clippy::too_many_arguments)]
 pub async fn call_multiple_connectors_service<F, Op, Req, Ctx>(
     state: &AppState,
     merchant_account: &domain::MerchantAccount,
@@ -799,6 +950,7 @@ pub async fn call_multiple_connectors_service<F, Op, Req, Ctx>(
     _operation: &Op,
     mut payment_data: PaymentData<F>,
     customer: &Option<domain::Customer>,
+    session_surcharge_details: Option<api::SessionSurchargeDetails>,
 ) -> RouterResult<PaymentData<F>>
 where
     Op: Debug,
@@ -818,19 +970,6 @@ where
 {
     let call_connectors_start_time = Instant::now();
     let mut join_handlers = Vec::with_capacity(connectors.len());
-    let surcharge_metadata = payment_data
-        .payment_attempt
-        .surcharge_metadata
-        .as_ref()
-        .map(|surcharge_metadata_value| {
-            surcharge_metadata_value
-                .clone()
-                .parse_value::<SurchargeMetadata>("SurchargeMetadata")
-        })
-        .transpose()
-        .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("Failed to Deserialize SurchargeMetadata")?;
-
     for session_connector_data in connectors.iter() {
         let connector_id = session_connector_data.connector.connector.id();
 
@@ -839,18 +978,25 @@ where
             merchant_account,
             &mut payment_data,
             &session_connector_data.connector.connector_name.to_string(),
+            session_connector_data
+                .connector
+                .merchant_connector_id
+                .as_ref(),
             key_store,
             false,
         )
         .await?;
+
         payment_data.surcharge_details =
-            surcharge_metadata.as_ref().and_then(|surcharge_metadata| {
-                let payment_method_type = session_connector_data.payment_method_type;
-                surcharge_metadata
-                    .surcharge_results
-                    .get(&payment_method_type.to_string())
-                    .cloned()
-            });
+            session_surcharge_details
+                .as_ref()
+                .and_then(|session_surcharge_details| {
+                    session_surcharge_details.fetch_surcharge_details(
+                        &session_connector_data.payment_method_type.into(),
+                        &session_connector_data.payment_method_type,
+                        None,
+                    )
+                });
 
         let router_data = payment_data
             .construct_router_data(
@@ -943,6 +1089,7 @@ where
                 &state.conf.connectors,
                 &connector_name,
                 api::GetToken::Connector,
+                merchant_connector_account.get_mca_id(),
             )?;
 
             let connector_label = super::utils::get_connector_label(
@@ -952,7 +1099,9 @@ where
                 &connector_name,
             );
 
-            let connector_label = if let Some(connector_label) = connector_label {
+            let connector_label = if let Some(connector_label) =
+                merchant_connector_account.get_mca_id().or(connector_label)
+            {
                 connector_label
             } else {
                 let profile_id = utils::get_profile_id_from_business_details(
@@ -1098,7 +1247,8 @@ pub async fn construct_profile_id_and_get_mca<'a, F>(
     state: &'a AppState,
     merchant_account: &domain::MerchantAccount,
     payment_data: &mut PaymentData<F>,
-    connector_id: &str,
+    connector_name: &str,
+    merchant_connector_id: Option<&String>,
     key_store: &domain::MerchantKeyStore,
     should_validate: bool,
 ) -> RouterResult<helpers::MerchantConnectorAccountType>
@@ -1123,7 +1273,8 @@ where
         payment_data.creds_identifier.to_owned(),
         key_store,
         &profile_id,
-        connector_id,
+        connector_name,
+        merchant_connector_id,
     )
     .await?;
 
@@ -1307,6 +1458,7 @@ pub async fn get_connector_tokenization_action_when_confirm_true<F, Req, Ctx>(
     payment_data: &mut PaymentData<F>,
     validate_result: &operations::ValidateResult<'_>,
     merchant_connector_account: &helpers::MerchantConnectorAccountType,
+    merchant_key_store: &domain::MerchantKeyStore,
 ) -> RouterResult<(PaymentData<F>, TokenizationAction)>
 where
     F: Send + Clone,
@@ -1369,7 +1521,12 @@ where
                 TokenizationAction::TokenizeInRouter => {
                     let (_operation, payment_method_data) = operation
                         .to_domain()?
-                        .make_pm_data(state, payment_data, validate_result.storage_scheme)
+                        .make_pm_data(
+                            state,
+                            payment_data,
+                            validate_result.storage_scheme,
+                            merchant_key_store,
+                        )
                         .await?;
                     payment_data.payment_method_data = payment_method_data;
                     TokenizationAction::SkipConnectorTokenization
@@ -1379,7 +1536,12 @@ where
                 TokenizationAction::TokenizeInConnectorAndRouter => {
                     let (_operation, payment_method_data) = operation
                         .to_domain()?
-                        .make_pm_data(state, payment_data, validate_result.storage_scheme)
+                        .make_pm_data(
+                            state,
+                            payment_data,
+                            validate_result.storage_scheme,
+                            merchant_key_store,
+                        )
                         .await?;
 
                     payment_data.payment_method_data = payment_method_data;
@@ -1415,6 +1577,7 @@ pub async fn tokenize_in_router_when_confirm_false<F, Req, Ctx>(
     operation: &BoxedOperation<'_, F, Req, Ctx>,
     payment_data: &mut PaymentData<F>,
     validate_result: &operations::ValidateResult<'_>,
+    merchant_key_store: &domain::MerchantKeyStore,
 ) -> RouterResult<PaymentData<F>>
 where
     F: Send + Clone,
@@ -1424,7 +1587,12 @@ where
     let payment_data = if !is_operation_confirm(operation) {
         let (_operation, payment_method_data) = operation
             .to_domain()?
-            .make_pm_data(state, payment_data, validate_result.storage_scheme)
+            .make_pm_data(
+                state,
+                payment_data,
+                validate_result.storage_scheme,
+                merchant_key_store,
+            )
             .await?;
         payment_data.payment_method_data = payment_method_data;
         payment_data
@@ -1452,6 +1620,12 @@ pub struct PaymentAddress {
     pub billing: Option<api::Address>,
 }
 
+#[derive(Clone)]
+pub struct MandateConnectorDetails {
+    pub connector: String,
+    pub merchant_connector_id: Option<String>,
+}
+
 #[derive(Clone)]
 pub struct PaymentData<F>
 where
@@ -1461,10 +1635,9 @@ where
     pub payment_intent: storage::PaymentIntent,
     pub payment_attempt: storage::PaymentAttempt,
     pub multiple_capture_data: Option<types::MultipleCaptureData>,
-    pub connector_response: storage::ConnectorResponse,
     pub amount: api::Amount,
     pub mandate_id: Option<api_models::payments::MandateIds>,
-    pub mandate_connector: Option<String>,
+    pub mandate_connector: Option<MandateConnectorDetails>,
     pub currency: storage_enums::Currency,
     pub setup_mandate: Option<MandateData>,
     pub address: PaymentAddress,
@@ -1554,10 +1727,7 @@ pub fn should_call_connector<Op: Debug, F: Clone>(
             !matches!(
                 payment_data.payment_intent.status,
                 storage_enums::IntentStatus::Failed | storage_enums::IntentStatus::Succeeded
-            ) && payment_data
-                .connector_response
-                .authentication_data
-                .is_none()
+            ) && payment_data.payment_attempt.authentication_data.is_none()
         }
         "PaymentStatus" => {
             matches!(
@@ -1818,7 +1988,7 @@ pub fn update_straight_through_routing<F>(
 where
     F: Send + Clone,
 {
-    let _: api::RoutingAlgorithm = request_straight_through
+    let _: api_models::routing::RoutingAlgorithm = request_straight_through
         .clone()
         .parse_value("RoutingAlgorithm")
         .attach_printable("Invalid straight through routing rules format")?;
@@ -1835,7 +2005,8 @@ pub async fn get_connector_choice<F, Req, Ctx>(
     merchant_account: &domain::MerchantAccount,
     key_store: &domain::MerchantKeyStore,
     payment_data: &mut PaymentData<F>,
-) -> RouterResult<Option<api::ConnectorCallType>>
+    eligible_connectors: Option<Vec<api_models::enums::RoutableConnectors>>,
+) -> RouterResult<Option<ConnectorCallType>>
 where
     F: Send + Clone,
     Ctx: PaymentMethodRetrieve,
@@ -1844,7 +2015,7 @@ where
         .to_domain()?
         .get_connector(
             merchant_account,
-            state,
+            &state.clone(),
             req,
             &payment_data.payment_intent,
             key_store,
@@ -1853,171 +2024,333 @@ where
 
     let connector = if should_call_connector(operation, payment_data) {
         Some(match connector_choice {
-            api::ConnectorChoice::SessionMultiple(session_connectors) => {
-                api::ConnectorCallType::Multiple(session_connectors)
+            api::ConnectorChoice::SessionMultiple(connectors) => {
+                let routing_output = perform_session_token_routing(
+                    state.clone(),
+                    merchant_account,
+                    key_store,
+                    payment_data,
+                    connectors,
+                )
+                .await?;
+                api::ConnectorCallType::SessionMultiple(routing_output)
             }
 
-            api::ConnectorChoice::StraightThrough(straight_through) => connector_selection(
-                state,
-                merchant_account,
-                payment_data,
-                Some(straight_through),
-            )?,
+            api::ConnectorChoice::StraightThrough(straight_through) => {
+                connector_selection(
+                    state,
+                    merchant_account,
+                    key_store,
+                    payment_data,
+                    Some(straight_through),
+                    eligible_connectors,
+                )
+                .await?
+            }
 
             api::ConnectorChoice::Decide => {
-                connector_selection(state, merchant_account, payment_data, None)?
+                connector_selection(
+                    state,
+                    merchant_account,
+                    key_store,
+                    payment_data,
+                    None,
+                    eligible_connectors,
+                )
+                .await?
             }
         })
-    } else if let api::ConnectorChoice::StraightThrough(val) = connector_choice {
-        update_straight_through_routing(payment_data, val)
+    } else if let api::ConnectorChoice::StraightThrough(algorithm) = connector_choice {
+        update_straight_through_routing(payment_data, algorithm)
             .change_context(errors::ApiErrorResponse::InternalServerError)
             .attach_printable("Failed to update straight through routing algorithm")?;
+
         None
     } else {
         None
     };
-
     Ok(connector)
 }
 
-pub fn connector_selection<F>(
+pub async fn connector_selection<F>(
     state: &AppState,
     merchant_account: &domain::MerchantAccount,
+    key_store: &domain::MerchantKeyStore,
     payment_data: &mut PaymentData<F>,
     request_straight_through: Option<serde_json::Value>,
-) -> RouterResult<api::ConnectorCallType>
+    eligible_connectors: Option<Vec<api_models::enums::RoutableConnectors>>,
+) -> RouterResult<ConnectorCallType>
 where
     F: Send + Clone,
 {
-    if let Some(ref connector_name) = payment_data.payment_attempt.connector {
-        let connector_data = api::ConnectorData::get_connector_by_name(
-            &state.conf.connectors,
-            connector_name,
-            api::GetToken::Connector,
-        )
-        .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("invalid connector name received in payment attempt")?;
-
-        return Ok(api::ConnectorCallType::Single(connector_data));
-    }
+    let request_straight_through: Option<api::routing::StraightThroughAlgorithm> =
+        request_straight_through
+            .map(|val| val.parse_value("RoutingAlgorithm"))
+            .transpose()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Invalid straight through routing rules format")?;
 
     let mut routing_data = storage::RoutingData {
         routed_through: payment_data.payment_attempt.connector.clone(),
-        algorithm: payment_data
+        #[cfg(feature = "connector_choice_mca_id")]
+        merchant_connector_id: payment_data.payment_attempt.merchant_connector_id.clone(),
+        #[cfg(not(feature = "connector_choice_mca_id"))]
+        business_sub_label: payment_data.payment_attempt.business_sub_label.clone(),
+        algorithm: request_straight_through.clone(),
+        routing_info: payment_data
             .payment_attempt
             .straight_through_algorithm
             .clone()
-            .map(|val| val.parse_value("RoutingAlgorithm"))
+            .map(|val| val.parse_value("PaymentRoutingInfo"))
             .transpose()
             .change_context(errors::ApiErrorResponse::InternalServerError)
-            .attach_printable("Invalid straight through algorithm format in payment attempt")?,
+            .attach_printable("Invalid straight through algorithm format found in payment attempt")?
+            .unwrap_or_else(|| storage::PaymentRoutingInfo {
+                algorithm: None,
+                pre_routing_results: None,
+            }),
     };
 
-    let request_straight_through: Option<api::StraightThroughAlgorithm> = request_straight_through
-        .map(|val| val.parse_value("StraightThroughAlgorithm"))
-        .transpose()
-        .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("Invalid straight through routing rules format")?;
-
     let decided_connector = decide_connector(
-        state,
+        state.clone(),
         merchant_account,
+        key_store,
+        payment_data,
         request_straight_through,
         &mut routing_data,
-    )?;
+        eligible_connectors,
+    )
+    .await?;
 
-    let encoded_algorithm = routing_data
-        .algorithm
-        .map(|algo| Encode::<api::RoutingAlgorithm>::encode_to_value(&algo))
-        .transpose()
-        .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("Unable to serialize routing algorithm to serde value")?;
+    let encoded_info =
+        Encode::<storage::PaymentRoutingInfo>::encode_to_value(&routing_data.routing_info)
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("error serializing payment routing info to serde value")?;
 
     payment_data.payment_attempt.connector = routing_data.routed_through;
-    payment_data.payment_attempt.straight_through_algorithm = encoded_algorithm;
+    #[cfg(feature = "connector_choice_mca_id")]
+    {
+        payment_data.payment_attempt.merchant_connector_id = routing_data.merchant_connector_id;
+    }
+    #[cfg(not(feature = "connector_choice_mca_id"))]
+    {
+        payment_data.payment_attempt.business_sub_label = routing_data.business_sub_label;
+    }
+    payment_data.payment_attempt.straight_through_algorithm = Some(encoded_info);
 
     Ok(decided_connector)
 }
 
-pub fn decide_connector(
-    state: &AppState,
+pub async fn decide_connector<F>(
+    state: AppState,
     merchant_account: &domain::MerchantAccount,
-    request_straight_through: Option<api::StraightThroughAlgorithm>,
+    key_store: &domain::MerchantKeyStore,
+    payment_data: &mut PaymentData<F>,
+    request_straight_through: Option<api::routing::StraightThroughAlgorithm>,
     routing_data: &mut storage::RoutingData,
-) -> RouterResult<api::ConnectorCallType> {
-    if let Some(ref connector_name) = routing_data.routed_through {
+    eligible_connectors: Option<Vec<api_models::enums::RoutableConnectors>>,
+) -> RouterResult<ConnectorCallType>
+where
+    F: Send + Clone,
+{
+    // If the connector was already decided previously, use the same connector
+    // This is in case of flows like payments_sync, payments_cancel where the successive operations
+    // with the connector have to be made using the same connector account.
+    if let Some(ref connector_name) = payment_data.payment_attempt.connector {
+        // Connector was already decided previously, use the same connector
         let connector_data = api::ConnectorData::get_connector_by_name(
             &state.conf.connectors,
-            connector_name.as_str(),
+            connector_name,
             api::GetToken::Connector,
+            payment_data.payment_attempt.merchant_connector_id.clone(),
         )
         .change_context(errors::ApiErrorResponse::InternalServerError)
         .attach_printable("Invalid connector name received in 'routed_through'")?;
 
-        return Ok(api::ConnectorCallType::Single(connector_data));
+        routing_data.routed_through = Some(connector_name.clone());
+        return Ok(api::ConnectorCallType::PreDetermined(connector_data));
     }
 
-    if let Some(routing_algorithm) = request_straight_through {
-        let connector_name = match &routing_algorithm {
-            api::StraightThroughAlgorithm::Single(conn) => conn.to_string(),
-        };
-
+    if let Some(mandate_connector_details) = payment_data.mandate_connector.as_ref() {
         let connector_data = api::ConnectorData::get_connector_by_name(
             &state.conf.connectors,
-            &connector_name,
+            &mandate_connector_details.connector,
             api::GetToken::Connector,
+            #[cfg(feature = "connector_choice_mca_id")]
+            mandate_connector_details.merchant_connector_id.clone(),
+            #[cfg(not(feature = "connector_choice_mca_id"))]
+            None,
         )
         .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("Invalid connector name received in routing algorithm")?;
+        .attach_printable("Invalid connector name received in 'routed_through'")?;
 
-        routing_data.routed_through = Some(connector_name);
-        routing_data.algorithm = Some(routing_algorithm);
-        return Ok(api::ConnectorCallType::Single(connector_data));
+        routing_data.routed_through = Some(mandate_connector_details.connector.clone());
+        #[cfg(feature = "connector_choice_mca_id")]
+        {
+            routing_data.merchant_connector_id =
+                mandate_connector_details.merchant_connector_id.clone();
+        }
+        return Ok(api::ConnectorCallType::PreDetermined(connector_data));
     }
 
-    if let Some(ref routing_algorithm) = routing_data.algorithm {
-        let connector_name = match routing_algorithm {
-            api::StraightThroughAlgorithm::Single(conn) => conn.to_string(),
-        };
+    if let Some((pre_routing_results, storage_pm_type)) = routing_data
+        .routing_info
+        .pre_routing_results
+        .as_ref()
+        .zip(payment_data.payment_attempt.payment_method_type.as_ref())
+    {
+        if let Some(choice) = pre_routing_results.get(storage_pm_type) {
+            let connector_data = api::ConnectorData::get_connector_by_name(
+                &state.conf.connectors,
+                &choice.connector.to_string(),
+                api::GetToken::Connector,
+                #[cfg(feature = "connector_choice_mca_id")]
+                choice.merchant_connector_id.clone(),
+                #[cfg(not(feature = "connector_choice_mca_id"))]
+                None,
+            )
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Invalid connector name received")?;
 
-        let connector_data = api::ConnectorData::get_connector_by_name(
-            &state.conf.connectors,
-            &connector_name,
-            api::GetToken::Connector,
-        )
-        .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("Invalid connector name received in routing algorithm")?;
+            routing_data.routed_through = Some(choice.connector.to_string());
+            #[cfg(feature = "connector_choice_mca_id")]
+            {
+                routing_data.merchant_connector_id = choice.merchant_connector_id.clone();
+            }
+            #[cfg(not(feature = "connector_choice_mca_id"))]
+            {
+                routing_data.business_sub_label = choice.sub_label.clone();
+            }
+            return Ok(api::ConnectorCallType::PreDetermined(connector_data));
+        }
+    }
 
-        routing_data.routed_through = Some(connector_name);
-        return Ok(api::ConnectorCallType::Single(connector_data));
+    if let Some(routing_algorithm) = request_straight_through {
+        let (mut connectors, check_eligibility) =
+            routing::perform_straight_through_routing(&routing_algorithm, payment_data)
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Failed execution of straight through routing")?;
+
+        if check_eligibility {
+            connectors = routing::perform_eligibility_analysis_with_fallback(
+                &state.clone(),
+                key_store,
+                merchant_account.modified_at.assume_utc().unix_timestamp(),
+                connectors,
+                payment_data,
+                eligible_connectors,
+                #[cfg(feature = "business_profile_routing")]
+                payment_data.payment_intent.profile_id.clone(),
+            )
+            .await
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("failed eligibility analysis and fallback")?;
+        }
+
+        let first_connector_choice = connectors
+            .first()
+            .ok_or(errors::ApiErrorResponse::IncorrectPaymentMethodConfiguration)
+            .into_report()
+            .attach_printable("Empty connector list returned")?
+            .clone();
+
+        let connector_data = connectors
+            .into_iter()
+            .map(|conn| {
+                api::ConnectorData::get_connector_by_name(
+                    &state.conf.connectors,
+                    &conn.connector.to_string(),
+                    api::GetToken::Connector,
+                    #[cfg(feature = "connector_choice_mca_id")]
+                    conn.merchant_connector_id.clone(),
+                    #[cfg(not(feature = "connector_choice_mca_id"))]
+                    None,
+                )
+            })
+            .collect::<CustomResult<Vec<_>, _>>()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Invalid connector name received")?;
+
+        routing_data.routed_through = Some(first_connector_choice.connector.to_string());
+        #[cfg(feature = "connector_choice_mca_id")]
+        {
+            routing_data.merchant_connector_id = first_connector_choice.merchant_connector_id;
+        }
+        #[cfg(not(feature = "connector_choice_mca_id"))]
+        {
+            routing_data.business_sub_label = first_connector_choice.sub_label.clone();
+        }
+        routing_data.routing_info.algorithm = Some(routing_algorithm);
+        return Ok(api::ConnectorCallType::Retryable(connector_data));
     }
 
-    let routing_algorithm = merchant_account
-        .routing_algorithm
-        .clone()
-        .get_required_value("RoutingAlgorithm")
-        .change_context(errors::ApiErrorResponse::PreconditionFailed {
-            message: "no routing algorithm has been configured".to_string(),
-        })?
-        .parse_value::<api::RoutingAlgorithm>("RoutingAlgorithm")
-        .change_context(errors::ApiErrorResponse::InternalServerError) // Deserialization failed
-        .attach_printable("Unable to deserialize merchant routing algorithm")?;
-
-    let connector_name = match routing_algorithm {
-        api::RoutingAlgorithm::Single(conn) => conn.to_string(),
-    };
+    if let Some(ref routing_algorithm) = routing_data.routing_info.algorithm {
+        let (mut connectors, check_eligibility) =
+            routing::perform_straight_through_routing(routing_algorithm, payment_data)
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Failed execution of straight through routing")?;
 
-    let connector_data = api::ConnectorData::get_connector_by_name(
-        &state.conf.connectors,
-        &connector_name,
-        api::GetToken::Connector,
-    )
-    .change_context(errors::ApiErrorResponse::InternalServerError)
-    .attach_printable("Routing algorithm gave invalid connector")?;
+        if check_eligibility {
+            connectors = routing::perform_eligibility_analysis_with_fallback(
+                &state,
+                key_store,
+                merchant_account.modified_at.assume_utc().unix_timestamp(),
+                connectors,
+                payment_data,
+                eligible_connectors,
+                #[cfg(feature = "business_profile_routing")]
+                payment_data.payment_intent.profile_id.clone(),
+            )
+            .await
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("failed eligibility analysis and fallback")?;
+        }
+
+        let first_connector_choice = connectors
+            .first()
+            .ok_or(errors::ApiErrorResponse::IncorrectPaymentMethodConfiguration)
+            .into_report()
+            .attach_printable("Empty connector list returned")?
+            .clone();
+
+        let connector_data = connectors
+            .into_iter()
+            .map(|conn| {
+                api::ConnectorData::get_connector_by_name(
+                    &state.conf.connectors,
+                    &conn.connector.to_string(),
+                    api::GetToken::Connector,
+                    #[cfg(feature = "connector_choice_mca_id")]
+                    conn.merchant_connector_id,
+                    #[cfg(not(feature = "connector_choice_mca_id"))]
+                    None,
+                )
+            })
+            .collect::<CustomResult<Vec<_>, _>>()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Invalid connector name received")?;
 
-    routing_data.routed_through = Some(connector_name);
+        routing_data.routed_through = Some(first_connector_choice.connector.to_string());
+        #[cfg(feature = "connector_choice_mca_id")]
+        {
+            routing_data.merchant_connector_id = first_connector_choice.merchant_connector_id;
+        }
+        #[cfg(not(feature = "connector_choice_mca_id"))]
+        {
+            routing_data.business_sub_label = first_connector_choice.sub_label;
+        }
+        return Ok(api::ConnectorCallType::Retryable(connector_data));
+    }
 
-    Ok(api::ConnectorCallType::Single(connector_data))
+    route_connector_v1(
+        &state,
+        merchant_account,
+        key_store,
+        payment_data,
+        routing_data,
+        eligible_connectors,
+    )
+    .await
 }
 
 pub fn should_add_task_to_process_tracker<F: Clone>(payment_data: &PaymentData<F>) -> bool {
@@ -2031,3 +2364,225 @@ pub fn should_add_task_to_process_tracker<F: Clone>(payment_data: &PaymentData<F
         )
     )
 }
+
+pub async fn perform_session_token_routing<F>(
+    state: AppState,
+    merchant_account: &domain::MerchantAccount,
+    key_store: &domain::MerchantKeyStore,
+    payment_data: &mut PaymentData<F>,
+    connectors: Vec<api::SessionConnectorData>,
+) -> RouterResult<Vec<api::SessionConnectorData>>
+where
+    F: Clone,
+{
+    let routing_info: Option<storage::PaymentRoutingInfo> = payment_data
+        .payment_attempt
+        .straight_through_algorithm
+        .clone()
+        .map(|val| val.parse_value("PaymentRoutingInfo"))
+        .transpose()
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("invalid payment routing info format found in payment attempt")?;
+
+    if let Some(storage::PaymentRoutingInfo {
+        pre_routing_results: Some(pre_routing_results),
+        ..
+    }) = routing_info
+    {
+        let mut payment_methods: rustc_hash::FxHashMap<
+            (String, enums::PaymentMethodType),
+            api::SessionConnectorData,
+        > = rustc_hash::FxHashMap::from_iter(connectors.iter().map(|c| {
+            (
+                (
+                    c.connector.connector_name.to_string(),
+                    c.payment_method_type,
+                ),
+                c.clone(),
+            )
+        }));
+
+        let mut final_list: Vec<api::SessionConnectorData> = Vec::new();
+        for (routed_pm_type, choice) in pre_routing_results.into_iter() {
+            if let Some(session_connector_data) =
+                payment_methods.remove(&(choice.to_string(), routed_pm_type))
+            {
+                final_list.push(session_connector_data);
+            }
+        }
+
+        if !final_list.is_empty() {
+            return Ok(final_list);
+        }
+    }
+
+    let routing_enabled_pms = std::collections::HashSet::from([
+        enums::PaymentMethodType::GooglePay,
+        enums::PaymentMethodType::ApplePay,
+        enums::PaymentMethodType::Klarna,
+        enums::PaymentMethodType::Paypal,
+    ]);
+
+    let mut chosen = Vec::<api::SessionConnectorData>::new();
+    for connector_data in &connectors {
+        if routing_enabled_pms.contains(&connector_data.payment_method_type) {
+            chosen.push(connector_data.clone());
+        }
+    }
+    let sfr = SessionFlowRoutingInput {
+        state: &state,
+        country: payment_data
+            .address
+            .billing
+            .as_ref()
+            .and_then(|address| address.address.as_ref())
+            .and_then(|details| details.country),
+        key_store,
+        merchant_account,
+        payment_attempt: &payment_data.payment_attempt,
+        payment_intent: &payment_data.payment_intent,
+
+        chosen,
+    };
+    let result = self_routing::perform_session_flow_routing(sfr)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("error performing session flow routing")?;
+
+    let mut final_list: Vec<api::SessionConnectorData> = Vec::new();
+
+    #[cfg(not(feature = "connector_choice_mca_id"))]
+    for mut connector_data in connectors {
+        if !routing_enabled_pms.contains(&connector_data.payment_method_type) {
+            final_list.push(connector_data);
+        } else if let Some(choice) = result.get(&connector_data.payment_method_type) {
+            if connector_data.connector.connector_name == choice.connector.connector_name {
+                connector_data.business_sub_label = choice.sub_label.clone();
+                final_list.push(connector_data);
+            }
+        }
+    }
+
+    #[cfg(feature = "connector_choice_mca_id")]
+    for connector_data in connectors {
+        if !routing_enabled_pms.contains(&connector_data.payment_method_type) {
+            final_list.push(connector_data);
+        } else if let Some(choice) = result.get(&connector_data.payment_method_type) {
+            if connector_data.connector.connector_name == choice.connector.connector_name {
+                final_list.push(connector_data);
+            }
+        }
+    }
+
+    Ok(final_list)
+}
+
+pub async fn route_connector_v1<F>(
+    state: &AppState,
+    merchant_account: &domain::MerchantAccount,
+    key_store: &domain::MerchantKeyStore,
+    payment_data: &mut PaymentData<F>,
+    routing_data: &mut storage::RoutingData,
+    eligible_connectors: Option<Vec<api_models::enums::RoutableConnectors>>,
+) -> RouterResult<ConnectorCallType>
+where
+    F: Send + Clone,
+{
+    #[cfg(not(feature = "business_profile_routing"))]
+    let algorithm_ref: api::routing::RoutingAlgorithmRef = merchant_account
+        .routing_algorithm
+        .clone()
+        .map(|ra| ra.parse_value("RoutingAlgorithmRef"))
+        .transpose()
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Could not decode merchant routing algorithm ref")?
+        .unwrap_or_default();
+
+    #[cfg(feature = "business_profile_routing")]
+    let algorithm_ref: api::routing::RoutingAlgorithmRef = {
+        let profile_id = payment_data
+            .payment_intent
+            .profile_id
+            .as_ref()
+            .get_required_value("profile_id")
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("'profile_id' not set in payment intent")?;
+
+        let business_profile = state
+            .store
+            .find_business_profile_by_profile_id(profile_id)
+            .await
+            .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound {
+                id: profile_id.to_string(),
+            })?;
+
+        business_profile
+            .routing_algorithm
+            .clone()
+            .map(|ra| ra.parse_value("RoutingAlgorithmRef"))
+            .transpose()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Could not decode merchant routing algorithm ref")?
+            .unwrap_or_default()
+    };
+
+    let connectors = routing::perform_static_routing_v1(
+        state,
+        &merchant_account.merchant_id,
+        algorithm_ref,
+        payment_data,
+    )
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)?;
+
+    let connectors = routing::perform_eligibility_analysis_with_fallback(
+        &state.clone(),
+        key_store,
+        merchant_account.modified_at.assume_utc().unix_timestamp(),
+        connectors,
+        payment_data,
+        eligible_connectors,
+        #[cfg(feature = "business_profile_routing")]
+        payment_data.payment_intent.profile_id.clone(),
+    )
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("failed eligibility analysis and fallback")?;
+
+    let first_connector_choice = connectors
+        .first()
+        .ok_or(errors::ApiErrorResponse::IncorrectPaymentMethodConfiguration)
+        .into_report()
+        .attach_printable("Empty connector list returned")?
+        .clone();
+
+    routing_data.routed_through = Some(first_connector_choice.connector.to_string());
+
+    #[cfg(feature = "connector_choice_mca_id")]
+    {
+        routing_data.merchant_connector_id = first_connector_choice.merchant_connector_id;
+    }
+    #[cfg(not(feature = "connector_choice_mca_id"))]
+    {
+        routing_data.business_sub_label = first_connector_choice.sub_label;
+    }
+
+    let connector_data = connectors
+        .into_iter()
+        .map(|conn| {
+            api::ConnectorData::get_connector_by_name(
+                &state.conf.connectors,
+                &conn.connector.to_string(),
+                api::GetToken::Connector,
+                #[cfg(feature = "connector_choice_mca_id")]
+                conn.merchant_connector_id,
+                #[cfg(not(feature = "connector_choice_mca_id"))]
+                None,
+            )
+        })
+        .collect::<CustomResult<Vec<_>, _>>()
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Invalid connector name received")?;
+
+    Ok(ConnectorCallType::Retryable(connector_data))
+}
diff --git a/crates/router/src/core/payments/access_token.rs b/crates/router/src/core/payments/access_token.rs
index 887b2b8f411e..af10e91b5a08 100644
--- a/crates/router/src/core/payments/access_token.rs
+++ b/crates/router/src/core/payments/access_token.rs
@@ -173,6 +173,7 @@ pub async fn refresh_connector_auth(
                     message: consts::REQUEST_TIMEOUT_ERROR_MESSAGE.to_string(),
                     reason: Some(consts::REQUEST_TIMEOUT_ERROR_MESSAGE.to_string()),
                     status_code: 504,
+                    attempt_status: None,
                 };
 
                 Ok(Err(error_response))
diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs
index ef0fce407f0d..46eaca26f7cc 100644
--- a/crates/router/src/core/payments/flows.rs
+++ b/crates/router/src/core/payments/flows.rs
@@ -144,6 +144,7 @@ impl<const T: u8>
 default_imp_for_complete_authorize!(
     connector::Aci,
     connector::Adyen,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Boku,
     connector::Cashtocode,
@@ -211,6 +212,7 @@ default_imp_for_webhook_source_verification!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Braintree,
@@ -289,6 +291,7 @@ default_imp_for_create_customer!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -365,6 +368,7 @@ default_imp_for_connector_redirect_response!(
     connector::Aci,
     connector::Adyen,
     connector::Bitpay,
+    connector::Bankofamerica,
     connector::Boku,
     connector::Cashtocode,
     connector::Coinbase,
@@ -415,6 +419,7 @@ default_imp_for_connector_request_id!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -495,6 +500,7 @@ default_imp_for_accept_dispute!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -595,6 +601,7 @@ default_imp_for_file_upload!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -672,6 +679,7 @@ default_imp_for_submit_evidence!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -749,6 +757,7 @@ default_imp_for_defend_dispute!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -827,6 +836,7 @@ default_imp_for_pre_processing_steps!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -885,6 +895,7 @@ default_imp_for_payouts!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -963,6 +974,7 @@ default_imp_for_payouts_create!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -1044,6 +1056,7 @@ default_imp_for_payouts_eligibility!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -1122,6 +1135,7 @@ default_imp_for_payouts_fulfill!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -1200,6 +1214,7 @@ default_imp_for_payouts_cancel!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -1279,6 +1294,7 @@ default_imp_for_payouts_quote!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -1358,6 +1374,7 @@ default_imp_for_payouts_recipient!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -1436,6 +1453,7 @@ default_imp_for_approve!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
@@ -1515,6 +1533,7 @@ default_imp_for_reject!(
     connector::Airwallex,
     connector::Authorizedotnet,
     connector::Bambora,
+    connector::Bankofamerica,
     connector::Bitpay,
     connector::Bluesnap,
     connector::Boku,
diff --git a/crates/router/src/core/payments/flows/approve_flow.rs b/crates/router/src/core/payments/flows/approve_flow.rs
index 24f7e05e7b9d..14b710de914a 100644
--- a/crates/router/src/core/payments/flows/approve_flow.rs
+++ b/crates/router/src/core/payments/flows/approve_flow.rs
@@ -25,7 +25,10 @@ impl
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
     ) -> RouterResult<types::PaymentsApproveRouterData> {
-        transformers::construct_payment_router_data::<api::Approve, types::PaymentsApproveData>(
+        Box::pin(transformers::construct_payment_router_data::<
+            api::Approve,
+            types::PaymentsApproveData,
+        >(
             state,
             self.clone(),
             connector_id,
@@ -33,7 +36,7 @@ impl
             key_store,
             customer,
             merchant_connector_account,
-        )
+        ))
         .await
     }
 }
diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs
index 0199339e86c6..04bd7f0b4338 100644
--- a/crates/router/src/core/payments/flows/authorize_flow.rs
+++ b/crates/router/src/core/payments/flows/authorize_flow.rs
@@ -1,5 +1,5 @@
 use async_trait::async_trait;
-use error_stack::{self, IntoReport, ResultExt};
+use error_stack;
 
 use super::{ConstructFlowSpecificData, Feature};
 use crate::{
@@ -39,7 +39,10 @@ impl
             types::PaymentsResponseData,
         >,
     > {
-        transformers::construct_payment_router_data::<api::Authorize, types::PaymentsAuthorizeData>(
+        Box::pin(transformers::construct_payment_router_data::<
+            api::Authorize,
+            types::PaymentsAuthorizeData,
+        >(
             state,
             self.clone(),
             connector_id,
@@ -47,7 +50,7 @@ impl
             key_store,
             customer,
             merchant_connector_account,
-        )
+        ))
         .await
     }
 }
@@ -96,7 +99,7 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
             metrics::PAYMENT_COUNT.add(&metrics::CONTEXT, 1, &[]); // Metrics
 
             if resp.request.setup_mandate_details.clone().is_some() {
-                let payment_method_id = tokenization::save_payment_method(
+                let payment_method_id = Box::pin(tokenization::save_payment_method(
                     state,
                     connector,
                     resp.to_owned(),
@@ -104,23 +107,17 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
                     merchant_account,
                     self.request.payment_method_type,
                     key_store,
-                )
+                ))
                 .await?;
-                Ok(
-                    mandate::mandate_procedure(state, resp, maybe_customer, payment_method_id)
-                        .await?,
+                Ok(mandate::mandate_procedure(
+                    state,
+                    resp,
+                    maybe_customer,
+                    payment_method_id,
+                    connector.merchant_connector_id.clone(),
                 )
+                .await?)
             } else {
-                let arbiter = actix::Arbiter::try_current()
-                    .ok_or(errors::ApiErrorResponse::InternalServerError)
-                    .into_report()
-                    .attach_printable("arbiter retrieval failure")
-                    .map_err(|err| {
-                        logger::error!(?err);
-                        err
-                    })
-                    .ok();
-
                 let connector = connector.clone();
                 let response = resp.clone();
                 let maybe_customer = maybe_customer.clone();
@@ -130,28 +127,23 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
 
                 logger::info!("Initiating async call to save_payment_method in locker");
 
-                arbiter.map(|arb| {
-                    arb.spawn(async move {
-                        logger::info!("Starting async call to save_payment_method in locker");
-
-                        let result = tokenization::save_payment_method(
-                            &state,
-                            &connector,
-                            response,
-                            &maybe_customer,
-                            &merchant_account,
-                            self.request.payment_method_type,
-                            &key_store,
-                        )
-                        .await;
-
-                        if let Err(err) = result {
-                            logger::error!(
-                                "Asynchronously saving card in locker failed : {:?}",
-                                err
-                            );
-                        }
-                    })
+                tokio::spawn(async move {
+                    logger::info!("Starting async call to save_payment_method in locker");
+
+                    let result = Box::pin(tokenization::save_payment_method(
+                        &state,
+                        &connector,
+                        response,
+                        &maybe_customer,
+                        &merchant_account,
+                        self.request.payment_method_type,
+                        &key_store,
+                    ))
+                    .await;
+
+                    if let Err(err) = result {
+                        logger::error!("Asynchronously saving card in locker failed : {:?}", err);
+                    }
                 });
 
                 Ok(resp)
diff --git a/crates/router/src/core/payments/flows/cancel_flow.rs b/crates/router/src/core/payments/flows/cancel_flow.rs
index 3a3ac1b5b0bb..5918380ee0b2 100644
--- a/crates/router/src/core/payments/flows/cancel_flow.rs
+++ b/crates/router/src/core/payments/flows/cancel_flow.rs
@@ -24,7 +24,10 @@ impl ConstructFlowSpecificData<api::Void, types::PaymentsCancelData, types::Paym
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
     ) -> RouterResult<types::PaymentsCancelRouterData> {
-        transformers::construct_payment_router_data::<api::Void, types::PaymentsCancelData>(
+        Box::pin(transformers::construct_payment_router_data::<
+            api::Void,
+            types::PaymentsCancelData,
+        >(
             state,
             self.clone(),
             connector_id,
@@ -32,7 +35,7 @@ impl ConstructFlowSpecificData<api::Void, types::PaymentsCancelData, types::Paym
             key_store,
             customer,
             merchant_connector_account,
-        )
+        ))
         .await
     }
 }
diff --git a/crates/router/src/core/payments/flows/capture_flow.rs b/crates/router/src/core/payments/flows/capture_flow.rs
index d6077e708a93..d2b7c8e91bdb 100644
--- a/crates/router/src/core/payments/flows/capture_flow.rs
+++ b/crates/router/src/core/payments/flows/capture_flow.rs
@@ -25,7 +25,10 @@ impl
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
     ) -> RouterResult<types::PaymentsCaptureRouterData> {
-        transformers::construct_payment_router_data::<api::Capture, types::PaymentsCaptureData>(
+        Box::pin(transformers::construct_payment_router_data::<
+            api::Capture,
+            types::PaymentsCaptureData,
+        >(
             state,
             self.clone(),
             connector_id,
@@ -33,7 +36,7 @@ impl
             key_store,
             customer,
             merchant_connector_account,
-        )
+        ))
         .await
     }
 }
diff --git a/crates/router/src/core/payments/flows/complete_authorize_flow.rs b/crates/router/src/core/payments/flows/complete_authorize_flow.rs
index 6fbbb01e1a64..44d8728fd4d2 100644
--- a/crates/router/src/core/payments/flows/complete_authorize_flow.rs
+++ b/crates/router/src/core/payments/flows/complete_authorize_flow.rs
@@ -35,7 +35,7 @@ impl
             types::PaymentsResponseData,
         >,
     > {
-        transformers::construct_payment_router_data::<
+        Box::pin(transformers::construct_payment_router_data::<
             api::CompleteAuthorize,
             types::CompleteAuthorizeData,
         >(
@@ -46,7 +46,7 @@ impl
             key_store,
             customer,
             merchant_connector_account,
-        )
+        ))
         .await
     }
 }
diff --git a/crates/router/src/core/payments/flows/psync_flow.rs b/crates/router/src/core/payments/flows/psync_flow.rs
index 36d418a3ae8c..cb7a764985d1 100644
--- a/crates/router/src/core/payments/flows/psync_flow.rs
+++ b/crates/router/src/core/payments/flows/psync_flow.rs
@@ -28,7 +28,10 @@ impl ConstructFlowSpecificData<api::PSync, types::PaymentsSyncData, types::Payme
     ) -> RouterResult<
         types::RouterData<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>,
     > {
-        transformers::construct_payment_router_data::<api::PSync, types::PaymentsSyncData>(
+        Box::pin(transformers::construct_payment_router_data::<
+            api::PSync,
+            types::PaymentsSyncData,
+        >(
             state,
             self.clone(),
             connector_id,
@@ -36,7 +39,7 @@ impl ConstructFlowSpecificData<api::PSync, types::PaymentsSyncData, types::Payme
             key_store,
             customer,
             merchant_connector_account,
-        )
+        ))
         .await
     }
 }
diff --git a/crates/router/src/core/payments/flows/reject_flow.rs b/crates/router/src/core/payments/flows/reject_flow.rs
index 396d98fb9708..910cc955e633 100644
--- a/crates/router/src/core/payments/flows/reject_flow.rs
+++ b/crates/router/src/core/payments/flows/reject_flow.rs
@@ -24,7 +24,10 @@ impl ConstructFlowSpecificData<api::Reject, types::PaymentsRejectData, types::Pa
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
     ) -> RouterResult<types::PaymentsRejectRouterData> {
-        transformers::construct_payment_router_data::<api::Reject, types::PaymentsRejectData>(
+        Box::pin(transformers::construct_payment_router_data::<
+            api::Reject,
+            types::PaymentsRejectData,
+        >(
             state,
             self.clone(),
             connector_id,
@@ -32,7 +35,7 @@ impl ConstructFlowSpecificData<api::Reject, types::PaymentsRejectData, types::Pa
             key_store,
             customer,
             merchant_connector_account,
-        )
+        ))
         .await
     }
 }
diff --git a/crates/router/src/core/payments/flows/session_flow.rs b/crates/router/src/core/payments/flows/session_flow.rs
index a6ae83ac1572..595a6f5e958e 100644
--- a/crates/router/src/core/payments/flows/session_flow.rs
+++ b/crates/router/src/core/payments/flows/session_flow.rs
@@ -32,7 +32,10 @@ impl
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
     ) -> RouterResult<types::PaymentsSessionRouterData> {
-        transformers::construct_payment_router_data::<api::Session, types::PaymentsSessionData>(
+        Box::pin(transformers::construct_payment_router_data::<
+            api::Session,
+            types::PaymentsSessionData,
+        >(
             state,
             self.clone(),
             connector_id,
@@ -40,7 +43,7 @@ impl
             key_store,
             customer,
             merchant_connector_account,
-        )
+        ))
         .await
     }
 }
diff --git a/crates/router/src/core/payments/flows/setup_mandate_flow.rs b/crates/router/src/core/payments/flows/setup_mandate_flow.rs
index 4860f091a2be..0c03c8ce123b 100644
--- a/crates/router/src/core/payments/flows/setup_mandate_flow.rs
+++ b/crates/router/src/core/payments/flows/setup_mandate_flow.rs
@@ -31,7 +31,7 @@ impl
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
     ) -> RouterResult<types::SetupMandateRouterData> {
-        transformers::construct_payment_router_data::<
+        Box::pin(transformers::construct_payment_router_data::<
             api::SetupMandate,
             types::SetupMandateRequestData,
         >(
@@ -42,7 +42,7 @@ impl
             key_store,
             customer,
             merchant_connector_account,
-        )
+        ))
         .await
     }
 }
@@ -75,7 +75,7 @@ impl Feature<api::SetupMandate, types::SetupMandateRequestData> for types::Setup
         .await
         .to_setup_mandate_failed_response()?;
 
-        let pm_id = tokenization::save_payment_method(
+        let pm_id = Box::pin(tokenization::save_payment_method(
             state,
             connector,
             resp.to_owned(),
@@ -83,10 +83,17 @@ impl Feature<api::SetupMandate, types::SetupMandateRequestData> for types::Setup
             merchant_account,
             self.request.payment_method_type,
             key_store,
-        )
+        ))
         .await?;
 
-        mandate::mandate_procedure(state, resp, maybe_customer, pm_id).await
+        mandate::mandate_procedure(
+            state,
+            resp,
+            maybe_customer,
+            pm_id,
+            connector.merchant_connector_id.clone(),
+        )
+        .await
     }
 
     async fn add_access_token<'a>(
@@ -201,7 +208,7 @@ impl types::SetupMandateRouterData {
                 .to_setup_mandate_failed_response()?;
 
                 let payment_method_type = self.request.payment_method_type;
-                let pm_id = tokenization::save_payment_method(
+                let pm_id = Box::pin(tokenization::save_payment_method(
                     state,
                     connector,
                     resp.to_owned(),
@@ -209,10 +216,17 @@ impl types::SetupMandateRouterData {
                     merchant_account,
                     payment_method_type,
                     key_store,
-                )
+                ))
                 .await?;
 
-                Ok(mandate::mandate_procedure(state, resp, maybe_customer, pm_id).await?)
+                Ok(mandate::mandate_procedure(
+                    state,
+                    resp,
+                    maybe_customer,
+                    pm_id,
+                    connector.merchant_connector_id.clone(),
+                )
+                .await?)
             }
             _ => Ok(self.clone()),
         }
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index f56ed5552217..b9e96ec36e11 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -221,8 +221,6 @@ pub async fn create_or_update_address_for_payment_by_request(
         None => match req_address {
             Some(address) => {
                 // generate a new address here
-                let customer_id = customer_id.get_required_value("customer_id")?;
-
                 let address_details = address.address.clone().unwrap_or_default();
                 Some(
                     db.insert_address_for_payments(
@@ -282,7 +280,6 @@ pub async fn create_or_find_address_for_payment_by_request(
         None => match req_address {
             Some(address) => {
                 // generate a new address here
-                let customer_id = customer_id.get_required_value("customer_id")?;
 
                 let address_details = address.address.clone().unwrap_or_default();
                 Some(
@@ -317,7 +314,7 @@ pub async fn get_domain_address_for_payments(
     address_details: api_models::payments::AddressDetails,
     address: &api_models::payments::Address,
     merchant_id: &str,
-    customer_id: &str,
+    customer_id: Option<&String>,
     payment_id: &str,
     key: &[u8],
     storage_scheme: enums::MerchantStorageScheme,
@@ -332,7 +329,7 @@ pub async fn get_domain_address_for_payments(
                 .async_lift(|inner| types::encrypt_optional(inner, key))
                 .await?,
             country_code: address.phone.as_ref().and_then(|a| a.country_code.clone()),
-            customer_id: customer_id.to_string(),
+            customer_id: customer_id.cloned(),
             merchant_id: merchant_id.to_string(),
             address_id: generate_id(consts::ID_LENGTH, "add"),
             city: address_details.city,
@@ -402,13 +399,14 @@ pub async fn get_token_pm_type_mandate_details(
     request: &api::PaymentsRequest,
     mandate_type: Option<api::MandateTransactionType>,
     merchant_account: &domain::MerchantAccount,
+    merchant_key_store: &domain::MerchantKeyStore,
 ) -> RouterResult<(
     Option<String>,
     Option<storage_enums::PaymentMethod>,
     Option<storage_enums::PaymentMethodType>,
     Option<MandateData>,
     Option<payments::RecurringMandatePaymentData>,
-    Option<String>,
+    Option<payments::MandateConnectorDetails>,
 )> {
     let mandate_data = request.mandate_data.clone().map(MandateData::foreign_from);
     match mandate_type {
@@ -430,7 +428,13 @@ pub async fn get_token_pm_type_mandate_details(
                 recurring_mandate_payment_data,
                 payment_method_type_,
                 mandate_connector,
-            ) = get_token_for_recurring_mandate(state, request, merchant_account).await?;
+            ) = get_token_for_recurring_mandate(
+                state,
+                request,
+                merchant_account,
+                merchant_key_store,
+            )
+            .await?;
             Ok((
                 token_,
                 payment_method_,
@@ -455,12 +459,13 @@ pub async fn get_token_for_recurring_mandate(
     state: &AppState,
     req: &api::PaymentsRequest,
     merchant_account: &domain::MerchantAccount,
+    merchant_key_store: &domain::MerchantKeyStore,
 ) -> RouterResult<(
     Option<String>,
     Option<storage_enums::PaymentMethod>,
     Option<payments::RecurringMandatePaymentData>,
     Option<storage_enums::PaymentMethodType>,
-    Option<String>,
+    Option<payments::MandateConnectorDetails>,
 )> {
     let db = &*state.store;
     let mandate_id = req.mandate_id.clone().get_required_value("mandate_id")?;
@@ -498,8 +503,15 @@ pub async fn get_token_for_recurring_mandate(
 
     let token = Uuid::new_v4().to_string();
     let payment_method_type = payment_method.payment_method_type;
+    let mandate_connector_details = payments::MandateConnectorDetails {
+        connector: mandate.connector,
+        merchant_connector_id: mandate.merchant_connector_id,
+    };
+
     if let diesel_models::enums::PaymentMethod::Card = payment_method.payment_method {
-        let _ = cards::get_lookup_key_from_locker(state, &token, &payment_method).await?;
+        let _ =
+            cards::get_lookup_key_from_locker(state, &token, &payment_method, merchant_key_store)
+                .await?;
         if let Some(payment_method_from_request) = req.payment_method {
             let pm: storage_enums::PaymentMethod = payment_method_from_request;
             if pm != payment_method.payment_method {
@@ -519,7 +531,7 @@ pub async fn get_token_for_recurring_mandate(
                 payment_method_type,
             }),
             payment_method.payment_method_type,
-            Some(mandate.connector),
+            Some(mandate_connector_details),
         ))
     } else {
         Ok((
@@ -529,7 +541,7 @@ pub async fn get_token_for_recurring_mandate(
                 payment_method_type,
             }),
             payment_method.payment_method_type,
-            Some(mandate.connector),
+            Some(mandate_connector_details),
         ))
     }
 }
@@ -758,25 +770,14 @@ fn validate_new_mandate_request(
 }
 
 pub fn validate_customer_id_mandatory_cases(
-    has_shipping: bool,
-    has_billing: bool,
     has_setup_future_usage: bool,
     customer_id: &Option<String>,
 ) -> RouterResult<()> {
-    match (
-        has_shipping,
-        has_billing,
-        has_setup_future_usage,
-        customer_id,
-    ) {
-        (true, _, _, None) | (_, true, _, None) | (_, _, true, None) => {
-            Err(errors::ApiErrorResponse::PreconditionFailed {
-                message: "customer_id is mandatory when shipping or billing \
-                address is given or when setup_future_usage is given"
-                    .to_string(),
-            })
-            .into_report()
-        }
+    match (has_setup_future_usage, customer_id) {
+        (true, None) => Err(errors::ApiErrorResponse::PreconditionFailed {
+            message: "customer_id is mandatory when setup_future_usage is given".to_string(),
+        })
+        .into_report(),
         _ => Ok(()),
     }
 }
@@ -1329,6 +1330,7 @@ pub async fn make_pm_data<'a, F: Clone, R, Ctx: PaymentMethodRetrieve>(
     operation: BoxedOperation<'a, F, R, Ctx>,
     state: &'a AppState,
     payment_data: &mut PaymentData<F>,
+    merchant_key_store: &domain::MerchantKeyStore,
 ) -> RouterResult<(
     BoxedOperation<'a, F, R, Ctx>,
     Option<api::PaymentMethodData>,
@@ -1382,6 +1384,7 @@ pub async fn make_pm_data<'a, F: Clone, R, Ctx: PaymentMethodRetrieve>(
             let (pm, supplementary_data) = vault::Vault::get_payment_method_data_from_locker(
                 state,
                 &hyperswitch_token,
+                merchant_key_store,
             )
             .await
             .attach_printable(
@@ -1411,6 +1414,7 @@ pub async fn make_pm_data<'a, F: Clone, R, Ctx: PaymentMethodRetrieve>(
                             &updated_pm,
                             payment_data.payment_intent.customer_id.to_owned(),
                             enums::PaymentMethod::Card,
+                            merchant_key_store,
                         )
                         .await?;
                         Some(updated_pm)
@@ -1451,6 +1455,7 @@ pub async fn make_pm_data<'a, F: Clone, R, Ctx: PaymentMethodRetrieve>(
                 state,
                 &payment_data.payment_intent,
                 &payment_data.payment_attempt,
+                merchant_key_store,
             )
             .await?;
 
@@ -1470,6 +1475,7 @@ pub async fn store_in_vault_and_generate_ppmt(
     payment_intent: &PaymentIntent,
     payment_attempt: &PaymentAttempt,
     payment_method: enums::PaymentMethod,
+    merchant_key_store: &domain::MerchantKeyStore,
 ) -> RouterResult<String> {
     let router_token = vault::Vault::store_payment_method_data_in_locker(
         state,
@@ -1477,6 +1483,7 @@ pub async fn store_in_vault_and_generate_ppmt(
         payment_method_data,
         payment_intent.customer_id.to_owned(),
         payment_method,
+        merchant_key_store,
     )
     .await?;
     let parent_payment_method_token = generate_id(consts::ID_LENGTH, "token");
@@ -1500,6 +1507,7 @@ pub async fn store_payment_method_data_in_vault(
     payment_intent: &PaymentIntent,
     payment_method: enums::PaymentMethod,
     payment_method_data: &api::PaymentMethodData,
+    merchant_key_store: &domain::MerchantKeyStore,
 ) -> RouterResult<Option<String>> {
     if should_store_payment_method_data_in_vault(
         &state.conf.temp_locker_enable_config,
@@ -1512,6 +1520,7 @@ pub async fn store_payment_method_data_in_vault(
             payment_intent,
             payment_attempt,
             payment_method,
+            merchant_key_store,
         )
         .await?;
 
@@ -1887,7 +1896,7 @@ pub(super) fn validate_payment_list_request_for_joins(
 
 pub fn get_handle_response_url(
     payment_id: String,
-    merchant_account: &domain::MerchantAccount,
+    business_profile: &diesel_models::business_profile::BusinessProfile,
     response: api::PaymentsResponse,
     connector: String,
 ) -> RouterResult<api::RedirectionResponse> {
@@ -1896,7 +1905,7 @@ pub fn get_handle_response_url(
     let redirection_response = make_pg_redirect_response(payment_id, &response, connector);
 
     let return_url = make_merchant_url_with_response(
-        merchant_account,
+        business_profile,
         redirection_response,
         payments_return_url,
         response.client_secret.as_ref(),
@@ -1904,11 +1913,11 @@ pub fn get_handle_response_url(
     )
     .attach_printable("Failed to make merchant url with response")?;
 
-    make_url_with_signature(&return_url, merchant_account)
+    make_url_with_signature(&return_url, business_profile)
 }
 
 pub fn make_merchant_url_with_response(
-    merchant_account: &domain::MerchantAccount,
+    business_profile: &diesel_models::business_profile::BusinessProfile,
     redirection_response: api::PgRedirectResponse,
     request_return_url: Option<&String>,
     client_secret: Option<&masking::Secret<String>>,
@@ -1916,7 +1925,7 @@ pub fn make_merchant_url_with_response(
 ) -> RouterResult<String> {
     // take return url if provided in the request else use merchant return url
     let url = request_return_url
-        .or(merchant_account.return_url.as_ref())
+        .or(business_profile.return_url.as_ref())
         .get_required_value("return_url")?;
 
     let status_check = redirection_response.status;
@@ -1926,7 +1935,7 @@ pub fn make_merchant_url_with_response(
         .into_report()
         .attach_printable("Expected client secret to be `Some`")?;
 
-    let merchant_url_with_response = if merchant_account.redirect_to_merchant_with_http_post {
+    let merchant_url_with_response = if business_profile.redirect_to_merchant_with_http_post {
         url::Url::parse_with_params(
             url,
             &[
@@ -2020,7 +2029,7 @@ pub fn make_pg_redirect_response(
 
 pub fn make_url_with_signature(
     redirect_url: &str,
-    merchant_account: &domain::MerchantAccount,
+    business_profile: &diesel_models::business_profile::BusinessProfile,
 ) -> RouterResult<api::RedirectionResponse> {
     let mut url = url::Url::parse(redirect_url)
         .into_report()
@@ -2030,8 +2039,8 @@ pub fn make_url_with_signature(
     let mut base_url = url.clone();
     base_url.query_pairs_mut().clear();
 
-    let url = if merchant_account.enable_payment_response_hash {
-        let key = merchant_account
+    let url = if business_profile.enable_payment_response_hash {
+        let key = business_profile
             .payment_response_hash_key
             .as_ref()
             .get_required_value("payment_response_hash_key")?;
@@ -2059,7 +2068,7 @@ pub fn make_url_with_signature(
         return_url: base_url.to_string(),
         params: parameters,
         return_url_with_query_params: url.to_string(),
-        http_method: if merchant_account.redirect_to_merchant_with_http_post {
+        http_method: if business_profile.redirect_to_merchant_with_http_post {
             services::Method::Post.to_string()
         } else {
             services::Method::Get.to_string()
@@ -2106,6 +2115,7 @@ pub fn generate_mandate(
     network_txn_id: Option<String>,
     payment_method_data_option: Option<api_models::payments::PaymentMethodData>,
     mandate_reference: Option<MandateReference>,
+    merchant_connector_id: Option<String>,
 ) -> CustomResult<Option<storage::MandateNew>, errors::ApiErrorResponse> {
     match (setup_mandate_details, customer) {
         (Some(data), Some(cus)) => {
@@ -2141,7 +2151,8 @@ pub fn generate_mandate(
                 }))
                 .set_connector_mandate_id(
                     mandate_reference.and_then(|reference| reference.connector_mandate_id),
-                );
+                )
+                .set_merchant_connector_id(merchant_connector_id);
 
             Ok(Some(
                 match data.mandate_type.get_required_value("mandate_type")? {
@@ -2410,6 +2421,7 @@ mod tests {
             profile_id: None,
             merchant_decision: None,
             payment_confirm_source: None,
+            surcharge_applicable: None,
             updated_by: storage_enums::MerchantStorageScheme::PostgresOnly.to_string(),
         };
         let req_cs = Some("1".to_string());
@@ -2459,6 +2471,7 @@ mod tests {
             profile_id: None,
             merchant_decision: None,
             payment_confirm_source: None,
+            surcharge_applicable: None,
             updated_by: storage_enums::MerchantStorageScheme::PostgresOnly.to_string(),
         };
         let req_cs = Some("1".to_string());
@@ -2508,6 +2521,7 @@ mod tests {
             profile_id: None,
             merchant_decision: None,
             payment_confirm_source: None,
+            surcharge_applicable: None,
             updated_by: storage_enums::MerchantStorageScheme::PostgresOnly.to_string(),
         };
         let req_cs = Some("1".to_string());
@@ -2591,6 +2605,13 @@ impl MerchantConnectorAccountType {
             Self::CacheVal(_) => None,
         }
     }
+
+    pub fn get_mca_id(&self) -> Option<String> {
+        match self {
+            Self::DbVal(db_val) => Some(db_val.merchant_connector_id.to_string()),
+            Self::CacheVal(_) => None,
+        }
+    }
 }
 
 /// Query for merchant connector account either by business label or profile id
@@ -2603,6 +2624,7 @@ pub async fn get_merchant_connector_account(
     key_store: &domain::MerchantKeyStore,
     profile_id: &String,
     connector_name: &str,
+    merchant_connector_id: Option<&String>,
 ) -> RouterResult<MerchantConnectorAccountType> {
     let db = &*state.store;
     match creds_identifier {
@@ -2645,17 +2667,31 @@ pub async fn get_merchant_connector_account(
             Ok(MerchantConnectorAccountType::CacheVal(res))
         }
         None => {
-            db.find_merchant_connector_account_by_profile_id_connector_name(
-                profile_id,
-                connector_name,
-                key_store,
-            )
-            .await
-            .to_not_found_response(
-                errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
-                    id: format!("profile id {profile_id} and connector name {connector_name}"),
-                },
-            )
+            if let Some(merchant_connector_id) = merchant_connector_id {
+                db.find_by_merchant_connector_account_merchant_id_merchant_connector_id(
+                    merchant_id,
+                    merchant_connector_id,
+                    key_store,
+                )
+                .await
+                .to_not_found_response(
+                    errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
+                        id: merchant_connector_id.to_string(),
+                    },
+                )
+            } else {
+                db.find_merchant_connector_account_by_profile_id_connector_name(
+                    profile_id,
+                    connector_name,
+                    key_store,
+                )
+                .await
+                .to_not_found_response(
+                    errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
+                        id: format!("profile id {profile_id} and connector name {connector_name}"),
+                    },
+                )
+            }
         }
         .map(MerchantConnectorAccountType::DbVal),
     }
@@ -2901,8 +2937,10 @@ impl AttemptType {
             multiple_capture_count: None,
             connector_response_reference_id: None,
             amount_capturable: old_payment_attempt.amount,
-            surcharge_metadata: old_payment_attempt.surcharge_metadata,
             updated_by: storage_scheme.to_string(),
+            authentication_data: None,
+            encoded_data: None,
+            merchant_connector_id: None,
         }
     }
 
@@ -2961,60 +2999,6 @@ impl AttemptType {
             }
         }
     }
-
-    #[instrument(skip_all)]
-    pub async fn get_or_insert_connector_response(
-        &self,
-        payment_attempt: &PaymentAttempt,
-        db: &dyn StorageInterface,
-        storage_scheme: storage::enums::MerchantStorageScheme,
-    ) -> RouterResult<storage::ConnectorResponse> {
-        match self {
-            Self::New => db
-                .insert_connector_response(
-                    payments::PaymentCreate::make_connector_response(payment_attempt),
-                    storage_scheme,
-                )
-                .await
-                .to_duplicate_response(errors::ApiErrorResponse::DuplicatePayment {
-                    payment_id: payment_attempt.payment_id.clone(),
-                }),
-            Self::SameOld => db
-                .find_connector_response_by_payment_id_merchant_id_attempt_id(
-                    &payment_attempt.payment_id,
-                    &payment_attempt.merchant_id,
-                    &payment_attempt.attempt_id,
-                    storage_scheme,
-                )
-                .await
-                .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound),
-        }
-    }
-
-    #[instrument(skip_all)]
-    pub async fn get_connector_response(
-        &self,
-        db: &dyn StorageInterface,
-        payment_id: &str,
-        merchant_id: &str,
-        attempt_id: &str,
-        storage_scheme: storage_enums::MerchantStorageScheme,
-    ) -> RouterResult<storage::ConnectorResponse> {
-        match self {
-            Self::New => Err(errors::ApiErrorResponse::InternalServerError)
-                .into_report()
-                .attach_printable("Precondition failed, the attempt type should not be `New`"),
-            Self::SameOld => db
-                .find_connector_response_by_payment_id_merchant_id_attempt_id(
-                    payment_id,
-                    merchant_id,
-                    attempt_id,
-                    storage_scheme,
-                )
-                .await
-                .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound),
-        }
-    }
 }
 
 #[inline(always)]
diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs
index d198cd562a79..f65e65459e00 100644
--- a/crates/router/src/core/payments/operations.rs
+++ b/crates/router/src/core/payments/operations.rs
@@ -123,6 +123,7 @@ pub trait Domain<F: Clone, R, Ctx: PaymentMethodRetrieve>: Send + Sync {
         state: &'a AppState,
         payment_data: &mut PaymentData<F>,
         storage_scheme: enums::MerchantStorageScheme,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'a, F, R, Ctx>,
         Option<api::PaymentMethodData>,
@@ -153,7 +154,7 @@ pub trait Domain<F: Clone, R, Ctx: PaymentMethodRetrieve>: Send + Sync {
 pub trait UpdateTracker<F, D, Req, Ctx: PaymentMethodRetrieve>: Send {
     async fn update_trackers<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         payment_data: D,
         customer: Option<domain::Customer>,
         storage_scheme: enums::MerchantStorageScheme,
@@ -170,7 +171,7 @@ pub trait UpdateTracker<F, D, Req, Ctx: PaymentMethodRetrieve>: Send {
 pub trait PostUpdateTracker<F, D, R>: Send {
     async fn update_tracker<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         payment_id: &api::PaymentIdType,
         payment_data: D,
         response: types::RouterData<F, R, PaymentsResponseData>,
@@ -233,11 +234,12 @@ where
         state: &'a AppState,
         payment_data: &mut PaymentData<F>,
         _storage_scheme: enums::MerchantStorageScheme,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'a, F, api::PaymentsRetrieveRequest, Ctx>,
         Option<api::PaymentMethodData>,
     )> {
-        helpers::make_pm_data(Box::new(self), state, payment_data).await
+        helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await
     }
 }
 
@@ -282,6 +284,7 @@ where
         _state: &'a AppState,
         _payment_data: &mut PaymentData<F>,
         _storage_scheme: enums::MerchantStorageScheme,
+        _merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'a, F, api::PaymentsCaptureRequest, Ctx>,
         Option<api::PaymentMethodData>,
@@ -343,6 +346,7 @@ where
         _state: &'a AppState,
         _payment_data: &mut PaymentData<F>,
         _storage_scheme: enums::MerchantStorageScheme,
+        _merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'a, F, api::PaymentsCancelRequest, Ctx>,
         Option<api::PaymentMethodData>,
@@ -394,6 +398,7 @@ where
         _state: &'a AppState,
         _payment_data: &mut PaymentData<F>,
         _storage_scheme: enums::MerchantStorageScheme,
+        _merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'a, F, api::PaymentsRejectRequest, Ctx>,
         Option<api::PaymentMethodData>,
diff --git a/crates/router/src/core/payments/operations/payment_approve.rs b/crates/router/src/core/payments/operations/payment_approve.rs
index a1d50a9049aa..538e65e4b22e 100644
--- a/crates/router/src/core/payments/operations/payment_approve.rs
+++ b/crates/router/src/core/payments/operations/payment_approve.rs
@@ -88,6 +88,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
             request,
             mandate_type.clone(),
             merchant_account,
+            key_store,
         )
         .await?;
 
@@ -130,8 +131,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
         amount = payment_attempt.amount.into();
 
         helpers::validate_customer_id_mandatory_cases(
-            request.shipping.is_some(),
-            request.billing.is_some(),
             request.setup_future_usage.is_some(),
             &payment_intent
                 .customer_id
@@ -162,16 +161,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
         )
         .await?;
 
-        let connector_response = db
-            .find_connector_response_by_payment_id_merchant_id_attempt_id(
-                &payment_attempt.payment_id,
-                &payment_attempt.merchant_id,
-                &payment_attempt.attempt_id,
-                storage_scheme,
-            )
-            .await
-            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
-
         let redirect_response = request
             .feature_metadata
             .as_ref()
@@ -225,7 +214,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 payment_intent,
                 payment_attempt,
                 currency,
-                connector_response,
                 amount,
                 email: request.email.clone(),
                 mandate_id: None,
@@ -301,12 +289,13 @@ impl<F: Clone + Send, Ctx: PaymentMethodRetrieve> Domain<F, api::PaymentsRequest
         state: &'a AppState,
         payment_data: &mut PaymentData<F>,
         _storage_scheme: storage_enums::MerchantStorageScheme,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'a, F, api::PaymentsRequest, Ctx>,
         Option<api::PaymentMethodData>,
     )> {
         let (op, payment_method_data) =
-            helpers::make_pm_data(Box::new(self), state, payment_data).await?;
+            helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await?;
 
         utils::when(payment_method_data.is_none(), || {
             Err(errors::ApiErrorResponse::PaymentMethodNotFound)
@@ -347,7 +336,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
     #[instrument(skip_all)]
     async fn update_trackers<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         mut payment_data: PaymentData<F>,
         _customer: Option<domain::Customer>,
         storage_scheme: storage_enums::MerchantStorageScheme,
@@ -367,6 +356,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
             updated_by: storage_scheme.to_string(),
         };
         payment_data.payment_intent = db
+            .store
             .update_payment_intent(
                 payment_data.payment_intent,
                 intent_status_update,
diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs
index 43fdc440e64d..535edf736ca6 100644
--- a/crates/router/src/core/payments/operations/payment_cancel.rs
+++ b/crates/router/src/core/payments/operations/payment_cancel.rs
@@ -14,7 +14,6 @@ use crate::{
         payment_methods::PaymentMethodRetrieve,
         payments::{helpers, operations, CustomerDetails, PaymentAddress, PaymentData},
     },
-    db::StorageInterface,
     routes::AppState,
     services,
     types::{
@@ -106,15 +105,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
         )
         .await?;
 
-        let connector_response = db
-            .find_connector_response_by_payment_id_merchant_id_attempt_id(
-                &payment_attempt.payment_id,
-                &payment_attempt.merchant_id,
-                &payment_attempt.attempt_id,
-                storage_scheme,
-            )
-            .await
-            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
         let currency = payment_attempt.currency.get_required_value("currency")?;
         let amount = payment_attempt.amount.into();
 
@@ -161,7 +151,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 refunds: vec![],
                 disputes: vec![],
                 attempts: None,
-                connector_response,
+
                 sessions_token: vec![],
                 card_cvc: None,
                 creds_identifier,
@@ -187,7 +177,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
     #[instrument(skip_all)]
     async fn update_trackers<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         mut payment_data: PaymentData<F>,
         _customer: Option<domain::Customer>,
         storage_scheme: enums::MerchantStorageScheme,
@@ -216,6 +206,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
 
         if let Some(payment_intent_update) = intent_status_update {
             payment_data.payment_intent = db
+                .store
                 .update_payment_intent(
                     payment_data.payment_intent,
                     payment_intent_update,
@@ -225,17 +216,18 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
                 .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
         }
 
-        db.update_payment_attempt_with_attempt_id(
-            payment_data.payment_attempt.clone(),
-            storage::PaymentAttemptUpdate::VoidUpdate {
-                status: attempt_status_update,
-                cancellation_reason,
-                updated_by: storage_scheme.to_string(),
-            },
-            storage_scheme,
-        )
-        .await
-        .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
+        db.store
+            .update_payment_attempt_with_attempt_id(
+                payment_data.payment_attempt.clone(),
+                storage::PaymentAttemptUpdate::VoidUpdate {
+                    status: attempt_status_update,
+                    cancellation_reason,
+                    updated_by: storage_scheme.to_string(),
+                },
+                storage_scheme,
+            )
+            .await
+            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
         Ok((Box::new(self), payment_data))
     }
 }
diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs
index 1cfcbce5532f..ff51a2c49d77 100644
--- a/crates/router/src/core/payments/operations/payment_capture.rs
+++ b/crates/router/src/core/payments/operations/payment_capture.rs
@@ -3,7 +3,6 @@ use std::marker::PhantomData;
 use api_models::enums::FrmSuggestion;
 use async_trait::async_trait;
 use common_utils::ext_traits::AsyncExt;
-use diesel_models::connector_response::ConnectorResponse;
 use error_stack::ResultExt;
 use router_env::{instrument, tracing};
 
@@ -14,13 +13,12 @@ use crate::{
         payment_methods::PaymentMethodRetrieve,
         payments::{self, helpers, operations, types::MultipleCaptureData},
     },
-    db::StorageInterface,
     routes::AppState,
     services,
     types::{
         api::{self, PaymentIdTypeExt},
         domain,
-        storage::{self, enums, payment_attempt::PaymentAttemptExt, ConnectorResponseExt},
+        storage::{self, enums, payment_attempt::PaymentAttemptExt},
     },
     utils::OptionExt,
 };
@@ -89,9 +87,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
 
         helpers::validate_capture_method(capture_method)?;
 
-        let (multiple_capture_data, connector_response) = if capture_method
-            == enums::CaptureMethod::ManualMultiple
-        {
+        let multiple_capture_data = if capture_method == enums::CaptureMethod::ManualMultiple {
             let amount_to_capture = request
                 .amount_to_capture
                 .get_required_value("amount_to_capture")?;
@@ -121,37 +117,13 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 .to_not_found_response(errors::ApiErrorResponse::DuplicatePayment {
                     payment_id: payment_id.clone(),
                 })?;
-            let new_connector_response = db
-                .insert_connector_response(
-                    ConnectorResponse::make_new_connector_response(
-                        capture.payment_id.clone(),
-                        capture.merchant_id.clone(),
-                        capture.capture_id.clone(),
-                        Some(capture.connector.clone()),
-                        storage_scheme.to_string(),
-                    ),
-                    storage_scheme,
-                )
-                .await
-                .to_not_found_response(errors::ApiErrorResponse::DuplicatePayment { payment_id })?;
-            (
-                Some(MultipleCaptureData::new_for_create(
-                    previous_captures,
-                    capture,
-                )),
-                new_connector_response,
-            )
+
+            Some(MultipleCaptureData::new_for_create(
+                previous_captures,
+                capture,
+            ))
         } else {
-            let connector_response = db
-                .find_connector_response_by_payment_id_merchant_id_attempt_id(
-                    &payment_attempt.payment_id,
-                    &payment_attempt.merchant_id,
-                    &payment_attempt.attempt_id,
-                    storage_scheme,
-                )
-                .await
-                .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
-            (None, connector_response)
+            None
         };
 
         currency = payment_attempt.currency.get_required_value("currency")?;
@@ -223,7 +195,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 refunds: vec![],
                 disputes: vec![],
                 attempts: None,
-                connector_response,
                 sessions_token: vec![],
                 card_cvc: None,
                 creds_identifier,
@@ -250,7 +221,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
     #[instrument(skip_all)]
     async fn update_trackers<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         mut payment_data: payments::PaymentData<F>,
         _customer: Option<domain::Customer>,
         storage_scheme: enums::MerchantStorageScheme,
@@ -267,6 +238,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
     {
         payment_data.payment_attempt = match &payment_data.multiple_capture_data {
             Some(multiple_capture_data) => db
+                .store
                 .update_payment_attempt_with_attempt_id(
                     payment_data.payment_attempt,
                     storage::PaymentAttemptUpdate::MultipleCaptureCountUpdate {
diff --git a/crates/router/src/core/payments/operations/payment_complete_authorize.rs b/crates/router/src/core/payments/operations/payment_complete_authorize.rs
index 0e357f08734e..c648d95a4950 100644
--- a/crates/router/src/core/payments/operations/payment_complete_authorize.rs
+++ b/crates/router/src/core/payments/operations/payment_complete_authorize.rs
@@ -87,6 +87,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
             request,
             mandate_type.clone(),
             merchant_account,
+            key_store,
         )
         .await?;
 
@@ -139,8 +140,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
         amount = payment_attempt.amount.into();
 
         helpers::validate_customer_id_mandatory_cases(
-            request.shipping.is_some(),
-            request.billing.is_some(),
             request.setup_future_usage.is_some(),
             &payment_intent
                 .customer_id
@@ -171,16 +170,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
         )
         .await?;
 
-        let connector_response = db
-            .find_connector_response_by_payment_id_merchant_id_attempt_id(
-                &payment_attempt.payment_id,
-                &payment_attempt.merchant_id,
-                &payment_attempt.attempt_id,
-                storage_scheme,
-            )
-            .await
-            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
-
         let redirect_response = request
             .feature_metadata
             .as_ref()
@@ -220,7 +209,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 payment_intent,
                 payment_attempt,
                 currency,
-                connector_response,
                 amount,
                 email: request.email.clone(),
                 mandate_id: None,
@@ -296,12 +284,13 @@ impl<F: Clone + Send, Ctx: PaymentMethodRetrieve> Domain<F, api::PaymentsRequest
         state: &'a AppState,
         payment_data: &mut PaymentData<F>,
         _storage_scheme: storage_enums::MerchantStorageScheme,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'a, F, api::PaymentsRequest, Ctx>,
         Option<api::PaymentMethodData>,
     )> {
         let (op, payment_method_data) =
-            helpers::make_pm_data(Box::new(self), state, payment_data).await?;
+            helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await?;
         Ok((op, payment_method_data))
     }
 
@@ -337,7 +326,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
     #[instrument(skip_all)]
     async fn update_trackers<'b>(
         &'b self,
-        _db: &dyn StorageInterface,
+        _state: &'b AppState,
         payment_data: PaymentData<F>,
         _customer: Option<domain::Customer>,
         _storage_scheme: storage_enums::MerchantStorageScheme,
diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs
index 0e0d6c21479b..88462e7f8563 100644
--- a/crates/router/src/core/payments/operations/payment_confirm.rs
+++ b/crates/router/src/core/payments/operations/payment_confirm.rs
@@ -1,12 +1,17 @@
 use std::marker::PhantomData;
 
-use api_models::{enums::FrmSuggestion, payment_methods};
+use api_models::{
+    enums::FrmSuggestion,
+    payment_methods::{self, SurchargeDetailsResponse},
+};
 use async_trait::async_trait;
 use common_utils::ext_traits::{AsyncExt, Encode};
 use error_stack::ResultExt;
 use futures::FutureExt;
+use redis_interface::errors::RedisError;
 use router_derive::PaymentOperation;
 use router_env::{instrument, tracing};
+use tracing_futures::Instrument;
 
 use super::{BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, ValidateRequest};
 use crate::{
@@ -14,6 +19,7 @@ use crate::{
         errors::{self, CustomResult, RouterResult, StorageErrorExt},
         payment_methods::PaymentMethodRetrieve,
         payments::{self, helpers, operations, CustomerDetails, PaymentAddress, PaymentData},
+        utils::get_individual_surcharge_detail_from_redis,
     },
     db::StorageInterface,
     routes::AppState,
@@ -60,19 +66,46 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
 
         // Stage 1
 
-        let payment_intent_fut = db
-            .find_payment_intent_by_payment_id_merchant_id(&payment_id, merchant_id, storage_scheme)
-            .map(|x| x.change_context(errors::ApiErrorResponse::PaymentNotFound));
+        let store = state.clone().store;
+        let m_merchant_id = merchant_id.clone();
+        let payment_intent_fut = tokio::spawn(
+            async move {
+                store
+                    .find_payment_intent_by_payment_id_merchant_id(
+                        &payment_id,
+                        m_merchant_id.as_str(),
+                        storage_scheme,
+                    )
+                    .map(|x| x.change_context(errors::ApiErrorResponse::PaymentNotFound))
+                    .await
+            }
+            .in_current_span(),
+        );
 
-        let mandate_details_fut = helpers::get_token_pm_type_mandate_details(
-            state,
-            request,
-            mandate_type.clone(),
-            merchant_account,
+        let m_state = state.clone();
+        let m_mandate_type = mandate_type.clone();
+        let m_merchant_account = merchant_account.clone();
+        let m_request = request.clone();
+        let m_key_store = key_store.clone();
+
+        let mandate_details_fut = tokio::spawn(
+            async move {
+                helpers::get_token_pm_type_mandate_details(
+                    &m_state,
+                    &m_request,
+                    m_mandate_type,
+                    &m_merchant_account,
+                    &m_key_store,
+                )
+                .await
+            }
+            .in_current_span(),
         );
 
-        let (mut payment_intent, mandate_details) =
-            futures::try_join!(payment_intent_fut, mandate_details_fut)?;
+        let (mut payment_intent, mandate_details) = tokio::try_join!(
+            utils::flatten_join_error(payment_intent_fut),
+            utils::flatten_join_error(mandate_details_fut)
+        )?;
 
         helpers::validate_customer_access(&payment_intent, auth_flow, request)?;
 
@@ -106,127 +139,144 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
         // Stage 2
 
         let attempt_id = payment_intent.active_attempt.get_id();
-        let payment_attempt_fut = db
-            .find_payment_attempt_by_payment_id_merchant_id_attempt_id(
-                payment_intent.payment_id.as_str(),
-                merchant_id,
-                attempt_id.as_str(),
-                storage_scheme,
-            )
-            .map(|x| x.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound));
-
-        let shipping_address_fut = helpers::create_or_find_address_for_payment_by_request(
-            db,
-            request.shipping.as_ref(),
-            payment_intent.shipping_address_id.as_deref(),
-            merchant_id,
-            payment_intent
-                .customer_id
-                .as_ref()
-                .or(customer_details.customer_id.as_ref()),
-            key_store,
-            &payment_intent.payment_id,
-            merchant_account.storage_scheme,
+        let store = state.clone().store;
+        let m_payment_id = payment_intent.payment_id.clone();
+        let m_merchant_id = merchant_id.clone();
+
+        let payment_attempt_fut = tokio::spawn(
+            async move {
+                store
+                    .find_payment_attempt_by_payment_id_merchant_id_attempt_id(
+                        m_payment_id.as_str(),
+                        m_merchant_id.as_str(),
+                        attempt_id.as_str(),
+                        storage_scheme,
+                    )
+                    .map(|x| x.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound))
+                    .await
+            }
+            .in_current_span(),
         );
 
-        let billing_address_fut = helpers::create_or_find_address_for_payment_by_request(
-            db,
-            request.billing.as_ref(),
-            payment_intent.billing_address_id.as_deref(),
-            merchant_id,
-            payment_intent
-                .customer_id
-                .as_ref()
-                .or(customer_details.customer_id.as_ref()),
-            key_store,
-            &payment_intent.payment_id,
-            merchant_account.storage_scheme,
+        let m_merchant_id = merchant_id.clone();
+        let m_request_shipping = request.shipping.clone();
+        let m_payment_intent_shipping_address_id = payment_intent.shipping_address_id.clone();
+        let m_payment_intent_payment_id = payment_intent.payment_id.clone();
+        let m_customer_details_customer_id = customer_details.customer_id.clone();
+        let m_payment_intent_customer_id = payment_intent.customer_id.clone();
+        let store = state.clone().store;
+        let m_key_store = key_store.clone();
+
+        let shipping_address_fut = tokio::spawn(
+            async move {
+                helpers::create_or_find_address_for_payment_by_request(
+                    store.as_ref(),
+                    m_request_shipping.as_ref(),
+                    m_payment_intent_shipping_address_id.as_deref(),
+                    m_merchant_id.as_str(),
+                    m_payment_intent_customer_id
+                        .as_ref()
+                        .or(m_customer_details_customer_id.as_ref()),
+                    &m_key_store,
+                    m_payment_intent_payment_id.as_ref(),
+                    storage_scheme,
+                )
+                .await
+            }
+            .in_current_span(),
         );
 
-        let config_update_fut = request
-            .merchant_connector_details
-            .to_owned()
-            .async_map(|mcd| async {
-                helpers::insert_merchant_connector_creds_to_config(
-                    db,
-                    merchant_account.merchant_id.as_str(),
-                    mcd,
+        let m_merchant_id = merchant_id.clone();
+        let m_request_billing = request.billing.clone();
+        let m_customer_details_customer_id = customer_details.customer_id.clone();
+        let m_payment_intent_customer_id = payment_intent.customer_id.clone();
+        let m_payment_intent_billing_address_id = payment_intent.billing_address_id.clone();
+        let m_payment_intent_payment_id = payment_intent.payment_id.clone();
+        let store = state.clone().store;
+        let m_key_store = key_store.clone();
+
+        let billing_address_fut = tokio::spawn(
+            async move {
+                helpers::create_or_find_address_for_payment_by_request(
+                    store.as_ref(),
+                    m_request_billing.as_ref(),
+                    m_payment_intent_billing_address_id.as_deref(),
+                    m_merchant_id.as_ref(),
+                    m_payment_intent_customer_id
+                        .as_ref()
+                        .or(m_customer_details_customer_id.as_ref()),
+                    &m_key_store,
+                    m_payment_intent_payment_id.as_ref(),
+                    storage_scheme,
                 )
                 .await
-            })
-            .map(|x| x.transpose());
-
-        let (mut payment_attempt, shipping_address, billing_address, connector_response) =
-            match payment_intent.status {
-                api_models::enums::IntentStatus::RequiresCustomerAction
-                | api_models::enums::IntentStatus::RequiresMerchantAction
-                | api_models::enums::IntentStatus::RequiresPaymentMethod
-                | api_models::enums::IntentStatus::RequiresConfirmation => {
-                    let attempt_type = helpers::AttemptType::SameOld;
-
-                    let attempt_id = payment_intent.active_attempt.get_id();
-                    let connector_response_fut = attempt_type.get_connector_response(
-                        db,
-                        &payment_intent.payment_id,
-                        &payment_intent.merchant_id,
-                        attempt_id.as_str(),
-                        storage_scheme,
-                    );
-
-                    let (payment_attempt, shipping_address, billing_address, connector_response, _) =
-                        futures::try_join!(
-                            payment_attempt_fut,
-                            shipping_address_fut,
-                            billing_address_fut,
-                            connector_response_fut,
-                            config_update_fut
-                        )?;
+            }
+            .in_current_span(),
+        );
 
-                    (
-                        payment_attempt,
-                        shipping_address,
-                        billing_address,
-                        connector_response,
-                    )
-                }
-                _ => {
-                    let (mut payment_attempt, shipping_address, billing_address, _) = futures::try_join!(
-                        payment_attempt_fut,
-                        shipping_address_fut,
-                        billing_address_fut,
-                        config_update_fut
-                    )?;
-
-                    let attempt_type = helpers::get_attempt_type(
-                        &payment_intent,
-                        &payment_attempt,
-                        request,
-                        "confirm",
-                    )?;
-
-                    (payment_intent, payment_attempt) = attempt_type
-                        .modify_payment_intent_and_payment_attempt(
-                            // 3
-                            request,
-                            payment_intent,
-                            payment_attempt,
-                            db,
-                            storage_scheme,
+        let m_merchant_id = merchant_id.clone();
+        let store = state.clone().store;
+        let m_request_merchant_connector_details = request.merchant_connector_details.clone();
+
+        let config_update_fut = tokio::spawn(
+            async move {
+                m_request_merchant_connector_details
+                    .async_map(|mcd| async {
+                        helpers::insert_merchant_connector_creds_to_config(
+                            store.as_ref(),
+                            m_merchant_id.as_str(),
+                            mcd,
                         )
-                        .await?;
-
-                    let connector_response = attempt_type
-                        .get_or_insert_connector_response(&payment_attempt, db, storage_scheme)
-                        .await?;
+                        .await
+                    })
+                    .map(|x| x.transpose())
+                    .await
+            }
+            .in_current_span(),
+        );
 
-                    (
+        let (mut payment_attempt, shipping_address, billing_address) = match payment_intent.status {
+            api_models::enums::IntentStatus::RequiresCustomerAction
+            | api_models::enums::IntentStatus::RequiresMerchantAction
+            | api_models::enums::IntentStatus::RequiresPaymentMethod
+            | api_models::enums::IntentStatus::RequiresConfirmation => {
+                let (payment_attempt, shipping_address, billing_address, _) = tokio::try_join!(
+                    utils::flatten_join_error(payment_attempt_fut),
+                    utils::flatten_join_error(shipping_address_fut),
+                    utils::flatten_join_error(billing_address_fut),
+                    utils::flatten_join_error(config_update_fut)
+                )?;
+
+                (payment_attempt, shipping_address, billing_address)
+            }
+            _ => {
+                let (mut payment_attempt, shipping_address, billing_address, _) = tokio::try_join!(
+                    utils::flatten_join_error(payment_attempt_fut),
+                    utils::flatten_join_error(shipping_address_fut),
+                    utils::flatten_join_error(billing_address_fut),
+                    utils::flatten_join_error(config_update_fut)
+                )?;
+
+                let attempt_type = helpers::get_attempt_type(
+                    &payment_intent,
+                    &payment_attempt,
+                    request,
+                    "confirm",
+                )?;
+
+                (payment_intent, payment_attempt) = attempt_type
+                    .modify_payment_intent_and_payment_attempt(
+                        request,
+                        payment_intent,
                         payment_attempt,
-                        shipping_address,
-                        billing_address,
-                        connector_response,
+                        &*state.store,
+                        storage_scheme,
                     )
-                }
-            };
+                    .await?;
+
+                (payment_attempt, shipping_address, billing_address)
+            }
+        };
 
         payment_intent.order_details = request
             .get_order_details_as_value()
@@ -284,8 +334,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
         amount = payment_attempt.amount.into();
 
         helpers::validate_customer_id_mandatory_cases(
-            request.shipping.is_some(),
-            request.billing.is_some(),
             request.setup_future_usage.is_some(),
             &payment_intent
                 .customer_id
@@ -334,19 +382,17 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
             sm.mandate_type = payment_attempt.mandate_details.clone().or(sm.mandate_type);
             sm
         });
+        Self::validate_request_surcharge_details_with_session_surcharge_details(
+            state,
+            &payment_attempt,
+            request,
+        )
+        .await?;
 
-        // populate payment_data.surcharge_details from request
-        let surcharge_details = request.surcharge_details.map(|surcharge_details| {
-            payment_methods::SurchargeDetailsResponse {
-                surcharge: payment_methods::Surcharge::Fixed(surcharge_details.surcharge_amount),
-                tax_on_surcharge: None,
-                surcharge_amount: surcharge_details.surcharge_amount,
-                tax_on_surcharge_amount: surcharge_details.tax_amount.unwrap_or(0),
-                final_amount: payment_attempt.amount
-                    + surcharge_details.surcharge_amount
-                    + surcharge_details.tax_amount.unwrap_or(0),
-            }
-        });
+        let surcharge_details = Self::get_surcharge_details_from_payment_request_or_payment_attempt(
+            request,
+            &payment_attempt,
+        );
 
         Ok((
             Box::new(self),
@@ -355,7 +401,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 payment_intent,
                 payment_attempt,
                 currency,
-                connector_response,
                 amount,
                 email: request.email.clone(),
                 mandate_id: None,
@@ -425,12 +470,13 @@ impl<F: Clone + Send, Ctx: PaymentMethodRetrieve> Domain<F, api::PaymentsRequest
         state: &'a AppState,
         payment_data: &mut PaymentData<F>,
         _storage_scheme: storage_enums::MerchantStorageScheme,
+        key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'a, F, api::PaymentsRequest, Ctx>,
         Option<api::PaymentMethodData>,
     )> {
         let (op, payment_method_data) =
-            helpers::make_pm_data(Box::new(self), state, payment_data).await?;
+            helpers::make_pm_data(Box::new(self), state, payment_data, key_store).await?;
 
         utils::when(payment_method_data.is_none(), || {
             Err(errors::ApiErrorResponse::PaymentMethodNotFound)
@@ -471,7 +517,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
     #[instrument(skip_all)]
     async fn update_trackers<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        state: &'b AppState,
         mut payment_data: PaymentData<F>,
         customer: Option<domain::Customer>,
         storage_scheme: storage_enums::MerchantStorageScheme,
@@ -514,6 +560,8 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
         };
 
         let connector = payment_data.payment_attempt.connector.clone();
+        let merchant_connector_id = payment_data.payment_attempt.merchant_connector_id.clone();
+
         let straight_through_algorithm = payment_data
             .payment_attempt
             .straight_through_algorithm
@@ -525,7 +573,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
             .payment_method_data
             .as_ref()
             .async_map(|payment_method_data| async {
-                helpers::get_additional_payment_data(payment_method_data, db).await
+                helpers::get_additional_payment_data(payment_method_data, &*state.store).await
             })
             .await
             .as_ref()
@@ -556,90 +604,136 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
             .take();
         let order_details = payment_data.payment_intent.order_details.clone();
         let metadata = payment_data.payment_intent.metadata.clone();
-        let surcharge_amount = payment_data
-            .surcharge_details
-            .as_ref()
-            .map(|surcharge_details| surcharge_details.surcharge_amount);
-        let tax_amount = payment_data
-            .surcharge_details
-            .as_ref()
-            .map(|surcharge_details| surcharge_details.tax_on_surcharge_amount);
         let authorized_amount = payment_data
             .surcharge_details
             .as_ref()
             .map(|surcharge_details| surcharge_details.final_amount)
             .unwrap_or(payment_data.payment_attempt.amount);
-        let payment_attempt_fut = db
-            .update_payment_attempt_with_attempt_id(
-                payment_data.payment_attempt,
-                storage::PaymentAttemptUpdate::ConfirmUpdate {
-                    amount: payment_data.amount.into(),
-                    currency: payment_data.currency,
-                    status: attempt_status,
-                    payment_method,
-                    authentication_type,
-                    browser_info,
-                    connector,
-                    payment_token,
-                    payment_method_data: additional_pm_data,
-                    payment_method_type,
-                    payment_experience,
-                    business_sub_label,
-                    straight_through_algorithm,
-                    error_code,
-                    error_message,
-                    amount_capturable: Some(authorized_amount),
-                    surcharge_amount,
-                    tax_amount,
-                    updated_by: storage_scheme.to_string(),
-                },
-                storage_scheme,
-            )
-            .map(|x| x.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound));
-
-        let payment_intent_fut = db
-            .update_payment_intent(
-                payment_data.payment_intent,
-                storage::PaymentIntentUpdate::Update {
-                    amount: payment_data.amount.into(),
-                    currency: payment_data.currency,
-                    setup_future_usage,
-                    status: intent_status,
-                    customer_id,
-                    shipping_address_id: shipping_address,
-                    billing_address_id: billing_address,
-                    return_url,
-                    business_country,
-                    business_label,
-                    description,
-                    statement_descriptor_name,
-                    statement_descriptor_suffix,
-                    order_details,
-                    metadata,
-                    payment_confirm_source: header_payload.payment_confirm_source,
-                    updated_by: storage_scheme.to_string(),
-                },
-                storage_scheme,
-            )
-            .map(|x| x.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound));
 
-        let customer_fut = Box::pin(async {
-            if let Some((updated_customer, customer)) = updated_customer.zip(customer) {
-                db.update_customer_by_customer_id_merchant_id(
-                    customer.customer_id.to_owned(),
-                    customer.merchant_id.to_owned(),
-                    updated_customer,
-                    key_store,
+        let m_payment_data_payment_attempt = payment_data.payment_attempt.clone();
+        let m_browser_info = browser_info.clone();
+        let m_connector = connector.clone();
+        let m_payment_token = payment_token.clone();
+        let m_additional_pm_data = additional_pm_data.clone();
+        let m_business_sub_label = business_sub_label.clone();
+        let m_straight_through_algorithm = straight_through_algorithm.clone();
+        let m_error_code = error_code.clone();
+        let m_error_message = error_message.clone();
+        let m_db = state.clone().store;
+
+        let payment_attempt_fut = tokio::spawn(
+            async move {
+                m_db.update_payment_attempt_with_attempt_id(
+                    m_payment_data_payment_attempt,
+                    storage::PaymentAttemptUpdate::ConfirmUpdate {
+                        amount: payment_data.amount.into(),
+                        currency: payment_data.currency,
+                        status: attempt_status,
+                        payment_method,
+                        authentication_type,
+                        browser_info: m_browser_info,
+                        connector: m_connector,
+                        payment_token: m_payment_token,
+                        payment_method_data: m_additional_pm_data,
+                        payment_method_type,
+                        payment_experience,
+                        business_sub_label: m_business_sub_label,
+                        straight_through_algorithm: m_straight_through_algorithm,
+                        error_code: m_error_code,
+                        error_message: m_error_message,
+                        amount_capturable: Some(authorized_amount),
+                        updated_by: storage_scheme.to_string(),
+                        merchant_connector_id,
+                    },
+                    storage_scheme,
+                )
+                .map(|x| x.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound))
+                .await
+            }
+            .in_current_span(),
+        );
+
+        let m_payment_data_payment_intent = payment_data.payment_intent.clone();
+        let m_customer_id = customer_id.clone();
+        let m_shipping_address_id = shipping_address.clone();
+        let m_billing_address_id = billing_address.clone();
+        let m_return_url = return_url.clone();
+        let m_business_label = business_label.clone();
+        let m_description = description.clone();
+        let m_statement_descriptor_name = statement_descriptor_name.clone();
+        let m_statement_descriptor_suffix = statement_descriptor_suffix.clone();
+        let m_order_details = order_details.clone();
+        let m_metadata = metadata.clone();
+        let m_db = state.clone().store;
+        let m_storage_scheme = storage_scheme.to_string();
+
+        let payment_intent_fut = tokio::spawn(
+            async move {
+                m_db.update_payment_intent(
+                    m_payment_data_payment_intent,
+                    storage::PaymentIntentUpdate::Update {
+                        amount: payment_data.amount.into(),
+                        currency: payment_data.currency,
+                        setup_future_usage,
+                        status: intent_status,
+                        customer_id: m_customer_id,
+                        shipping_address_id: m_shipping_address_id,
+                        billing_address_id: m_billing_address_id,
+                        return_url: m_return_url,
+                        business_country,
+                        business_label: m_business_label,
+                        description: m_description,
+                        statement_descriptor_name: m_statement_descriptor_name,
+                        statement_descriptor_suffix: m_statement_descriptor_suffix,
+                        order_details: m_order_details,
+                        metadata: m_metadata,
+                        payment_confirm_source: header_payload.payment_confirm_source,
+                        updated_by: m_storage_scheme,
+                    },
+                    storage_scheme,
                 )
+                .map(|x| x.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound))
                 .await
-                .change_context(errors::ApiErrorResponse::InternalServerError)
-                .attach_printable("Failed to update CustomerConnector in customer")?;
+            }
+            .in_current_span(),
+        );
+
+        let customer_fut =
+            if let Some((updated_customer, customer)) = updated_customer.zip(customer) {
+                let m_customer_customer_id = customer.customer_id.to_owned();
+                let m_customer_merchant_id = customer.merchant_id.to_owned();
+                let m_key_store = key_store.clone();
+                let m_updated_customer = updated_customer.clone();
+                let m_db = state.clone().store;
+                tokio::spawn(
+                    async move {
+                        m_db.update_customer_by_customer_id_merchant_id(
+                            m_customer_customer_id,
+                            m_customer_merchant_id,
+                            m_updated_customer,
+                            &m_key_store,
+                        )
+                        .await
+                        .change_context(errors::ApiErrorResponse::InternalServerError)
+                        .attach_printable("Failed to update CustomerConnector in customer")?;
+
+                        Ok::<_, error_stack::Report<errors::ApiErrorResponse>>(())
+                    }
+                    .in_current_span(),
+                )
+            } else {
+                tokio::spawn(
+                    async move { Ok::<_, error_stack::Report<errors::ApiErrorResponse>>(()) }
+                        .in_current_span(),
+                )
             };
-            Ok::<_, error_stack::Report<errors::ApiErrorResponse>>(())
-        });
 
-        let (payment_intent, payment_attempt, _) =
-            futures::try_join!(payment_intent_fut, payment_attempt_fut, customer_fut)?;
+        let (payment_intent, payment_attempt, _) = tokio::try_join!(
+            utils::flatten_join_error(payment_intent_fut),
+            utils::flatten_join_error(payment_attempt_fut),
+            utils::flatten_join_error(customer_fut)
+        )?;
+
         payment_data.payment_intent = payment_intent;
         payment_data.payment_attempt = payment_attempt;
 
@@ -698,3 +792,92 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve> ValidateRequest<F, api::Paymen
         ))
     }
 }
+
+impl PaymentConfirm {
+    pub async fn validate_request_surcharge_details_with_session_surcharge_details(
+        state: &AppState,
+        payment_attempt: &storage::PaymentAttempt,
+        request: &api::PaymentsRequest,
+    ) -> RouterResult<()> {
+        match (
+            request.surcharge_details,
+            request.payment_method_data.as_ref(),
+        ) {
+            (Some(request_surcharge_details), Some(payment_method_data)) => {
+                if let Some(payment_method_type) =
+                    payment_method_data.get_payment_method_type_if_session_token_type()
+                {
+                    let invalid_surcharge_details_error = Err(errors::ApiErrorResponse::InvalidRequestData {
+                        message: "surcharge_details sent in session token flow doesn't match with the one sent in confirm request".into(),
+                    }.into());
+                    if let Some(attempt_surcharge_amount) = payment_attempt.surcharge_amount {
+                        // payment_attempt.surcharge_amount will be Some if some surcharge was sent in payment create
+                        // if surcharge was sent in payment create call, the same would have been sent to the connector during session call
+                        // So verify the same
+                        if request_surcharge_details.surcharge_amount != attempt_surcharge_amount
+                            || request_surcharge_details.tax_amount != payment_attempt.tax_amount
+                        {
+                            return invalid_surcharge_details_error;
+                        }
+                    } else {
+                        // if not sent in payment create
+                        // verify that any calculated surcharge sent in session flow is same as the one sent in confirm
+                        return match get_individual_surcharge_detail_from_redis(
+                            state,
+                            &payment_method_type.into(),
+                            &payment_method_type,
+                            None,
+                            &payment_attempt.attempt_id,
+                        )
+                        .await
+                        {
+                            Ok(surcharge_details) => utils::when(
+                                !surcharge_details
+                                    .is_request_surcharge_matching(request_surcharge_details),
+                                || invalid_surcharge_details_error,
+                            ),
+                            Err(err) if err.current_context() == &RedisError::NotFound => {
+                                utils::when(!request_surcharge_details.is_surcharge_zero(), || {
+                                    invalid_surcharge_details_error
+                                })
+                            }
+                            Err(err) => Err(err)
+                                .change_context(errors::ApiErrorResponse::InternalServerError)
+                                .attach_printable("Failed to fetch redis value"),
+                        };
+                    }
+                }
+                Ok(())
+            }
+            (Some(_request_surcharge_details), None) => {
+                Err(errors::ApiErrorResponse::MissingRequiredField {
+                    field_name: "payment_method_data",
+                }
+                .into())
+            }
+            _ => Ok(()),
+        }
+    }
+
+    fn get_surcharge_details_from_payment_request_or_payment_attempt(
+        payment_request: &api::PaymentsRequest,
+        payment_attempt: &storage::PaymentAttempt,
+    ) -> Option<SurchargeDetailsResponse> {
+        payment_request
+            .surcharge_details
+            .map(|surcharge_details| {
+                surcharge_details.get_surcharge_details_object(payment_attempt.amount)
+            }) // if not passed in confirm request, look inside payment_attempt
+            .or(payment_attempt
+                .surcharge_amount
+                .map(|surcharge_amount| SurchargeDetailsResponse {
+                    surcharge: payment_methods::Surcharge::Fixed(surcharge_amount),
+                    tax_on_surcharge: None,
+                    surcharge_amount,
+                    tax_on_surcharge_amount: payment_attempt.tax_amount.unwrap_or(0),
+                    final_amount: payment_attempt.amount
+                        + surcharge_amount
+                        + payment_attempt.tax_amount.unwrap_or(0),
+                }))
+    }
+}
diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs
index 2cc15fbfc3cc..974f5e6ab5b6 100644
--- a/crates/router/src/core/payments/operations/payment_create.rs
+++ b/crates/router/src/core/payments/operations/payment_create.rs
@@ -1,6 +1,6 @@
 use std::marker::PhantomData;
 
-use api_models::enums::FrmSuggestion;
+use api_models::{enums::FrmSuggestion, payment_methods};
 use async_trait::async_trait;
 use common_utils::ext_traits::{AsyncExt, Encode, ValueExt};
 use data_models::{mandates::MandateData, payments::payment_attempt::PaymentAttempt};
@@ -16,7 +16,7 @@ use crate::{
         errors::{self, CustomResult, RouterResult, StorageErrorExt},
         payment_methods::PaymentMethodRetrieve,
         payments::{self, helpers, operations, CustomerDetails, PaymentAddress, PaymentData},
-        utils::{self as core_utils},
+        utils as core_utils,
     },
     db::StorageInterface,
     routes::AppState,
@@ -62,7 +62,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
         let ephemeral_key = Self::get_ephemeral_key(request, state, merchant_account).await;
         let merchant_id = &merchant_account.merchant_id;
         let storage_scheme = merchant_account.storage_scheme;
-        let (payment_intent, payment_attempt, connector_response);
+        let (payment_intent, payment_attempt);
 
         let money @ (amount, currency) = payments_create_request_validation(request)?;
 
@@ -107,6 +107,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
             request,
             mandate_type,
             merchant_account,
+            merchant_key_store,
         )
         .await?;
 
@@ -195,16 +196,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 payment_id: payment_id.clone(),
             })?;
 
-        connector_response = db
-            .insert_connector_response(
-                Self::make_connector_response(&payment_attempt),
-                storage_scheme,
-            )
-            .await
-            .to_duplicate_response(errors::ApiErrorResponse::DuplicatePayment {
-                payment_id: payment_id.clone(),
-            })?;
-
         let mandate_id = request
             .mandate_id
             .as_ref()
@@ -276,6 +267,19 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
         // The operation merges mandate data from both request and payment_attempt
         let setup_mandate: Option<MandateData> = setup_mandate.map(Into::into);
 
+        // populate payment_data.surcharge_details from request
+        let surcharge_details = request.surcharge_details.map(|surcharge_details| {
+            payment_methods::SurchargeDetailsResponse {
+                surcharge: payment_methods::Surcharge::Fixed(surcharge_details.surcharge_amount),
+                tax_on_surcharge: None,
+                surcharge_amount: surcharge_details.surcharge_amount,
+                tax_on_surcharge_amount: surcharge_details.tax_amount.unwrap_or(0),
+                final_amount: payment_attempt.amount
+                    + surcharge_details.surcharge_amount
+                    + surcharge_details.tax_amount.unwrap_or(0),
+            }
+        });
+
         Ok((
             operation,
             PaymentData {
@@ -299,7 +303,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 disputes: vec![],
                 attempts: None,
                 force_sync: None,
-                connector_response,
                 sessions_token: vec![],
                 card_cvc: request.card_cvc.clone(),
                 creds_identifier,
@@ -309,7 +312,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 ephemeral_key,
                 multiple_capture_data: None,
                 redirect_response: None,
-                surcharge_details: None,
+                surcharge_details,
                 frm_message: None,
                 payment_link_data,
             },
@@ -353,11 +356,12 @@ impl<F: Clone + Send, Ctx: PaymentMethodRetrieve> Domain<F, api::PaymentsRequest
         state: &'a AppState,
         payment_data: &mut PaymentData<F>,
         _storage_scheme: enums::MerchantStorageScheme,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'a, F, api::PaymentsRequest, Ctx>,
         Option<api::PaymentMethodData>,
     )> {
-        helpers::make_pm_data(Box::new(self), state, payment_data).await
+        helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await
     }
 
     #[instrument(skip_all)]
@@ -390,7 +394,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
     #[instrument(skip_all)]
     async fn update_trackers<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        state: &'b AppState,
         mut payment_data: PaymentData<F>,
         _customer: Option<domain::Customer>,
         storage_scheme: enums::MerchantStorageScheme,
@@ -428,8 +432,19 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
             .straight_through_algorithm
             .clone();
         let authorized_amount = payment_data.payment_attempt.amount;
+        let merchant_connector_id = payment_data.payment_attempt.merchant_connector_id.clone();
+
+        let surcharge_amount = payment_data
+            .surcharge_details
+            .as_ref()
+            .map(|surcharge_details| surcharge_details.surcharge_amount);
+        let tax_amount = payment_data
+            .surcharge_details
+            .as_ref()
+            .map(|surcharge_details| surcharge_details.tax_on_surcharge_amount);
 
-        payment_data.payment_attempt = db
+        payment_data.payment_attempt = state
+            .store
             .update_payment_attempt_with_attempt_id(
                 payment_data.payment_attempt,
                 storage::PaymentAttemptUpdate::UpdateTrackers {
@@ -440,7 +455,10 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
                         true => Some(authorized_amount),
                         false => None,
                     },
+                    surcharge_amount,
+                    tax_amount,
                     updated_by: storage_scheme.to_string(),
+                    merchant_connector_id,
                 },
                 storage_scheme,
             )
@@ -449,7 +467,8 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
 
         let customer_id = payment_data.payment_intent.customer_id.clone();
 
-        payment_data.payment_intent = db
+        payment_data.payment_intent = state
+            .store
             .update_payment_intent(
                 payment_data.payment_intent,
                 storage::PaymentIntentUpdate::ReturnUrlUpdate {
@@ -536,8 +555,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve> ValidateRequest<F, api::Paymen
             )?;
 
             helpers::validate_customer_id_mandatory_cases(
-                request.shipping.is_some(),
-                request.billing.is_some(),
                 request.setup_future_usage.is_some(),
                 &request
                     .customer
@@ -720,28 +737,11 @@ impl PaymentCreate {
             merchant_decision: None,
             payment_link_id,
             payment_confirm_source: None,
+            surcharge_applicable: None,
             updated_by: merchant_account.storage_scheme.to_string(),
         })
     }
 
-    #[instrument(skip_all)]
-    pub fn make_connector_response(
-        payment_attempt: &PaymentAttempt,
-    ) -> storage::ConnectorResponseNew {
-        storage::ConnectorResponseNew {
-            payment_id: payment_attempt.payment_id.clone(),
-            merchant_id: payment_attempt.merchant_id.clone(),
-            attempt_id: payment_attempt.attempt_id.clone(),
-            created_at: payment_attempt.created_at,
-            modified_at: payment_attempt.modified_at,
-            connector_name: payment_attempt.connector.clone(),
-            connector_transaction_id: None,
-            authentication_data: None,
-            encoded_data: None,
-            updated_by: payment_attempt.updated_by.clone(),
-        }
-    }
-
     #[instrument(skip_all)]
     pub async fn get_ephemeral_key(
         request: &api::PaymentsRequest,
@@ -810,6 +810,7 @@ async fn create_payment_link(
         created_at,
         last_modified_at,
         fulfilment_time: payment_link_object.link_expiry,
+        custom_merchant_name: payment_link_object.custom_merchant_name,
     };
     let payment_link_db = db
         .insert_payment_link(payment_link_req)
diff --git a/crates/router/src/core/payments/operations/payment_method_validate.rs b/crates/router/src/core/payments/operations/payment_method_validate.rs
index 6af25221b228..62f12cfbc90c 100644
--- a/crates/router/src/core/payments/operations/payment_method_validate.rs
+++ b/crates/router/src/core/payments/operations/payment_method_validate.rs
@@ -7,7 +7,7 @@ use error_stack::ResultExt;
 use router_derive::PaymentOperation;
 use router_env::{instrument, tracing};
 
-use super::{BoxedOperation, Domain, GetTracker, PaymentCreate, UpdateTracker, ValidateRequest};
+use super::{BoxedOperation, Domain, GetTracker, UpdateTracker, ValidateRequest};
 use crate::{
     consts,
     core::{
@@ -89,7 +89,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
         let merchant_id = &merchant_account.merchant_id;
         let storage_scheme = merchant_account.storage_scheme;
 
-        let (payment_intent, payment_attempt, connector_response);
+        let (payment_intent, payment_attempt);
 
         let payment_id = payment_id
             .get_payment_intent_id()
@@ -135,19 +135,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
             }
         }?;
 
-        connector_response = match db
-            .insert_connector_response(
-                PaymentCreate::make_connector_response(&payment_attempt),
-                storage_scheme,
-            )
-            .await
-        {
-            Ok(connector_resp) => Ok(connector_resp),
-            Err(err) => {
-                Err(err.change_context(errors::ApiErrorResponse::VerificationFailed { data: None }))
-            }
-        }?;
-
         let creds_identifier = request
             .merchant_connector_details
             .as_ref()
@@ -180,7 +167,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 mandate_connector: None,
                 setup_mandate: request.mandate_data.clone().map(Into::into),
                 token: request.payment_token.clone(),
-                connector_response,
                 payment_method_data: request.payment_method_data.clone(),
                 confirm: Some(true),
                 address: types::PaymentAddress::default(),
@@ -219,7 +205,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve> UpdateTracker<F, PaymentData<F>, api:
     #[instrument(skip_all)]
     async fn update_trackers<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        state: &'b AppState,
         mut payment_data: PaymentData<F>,
         _customer: Option<domain::Customer>,
         storage_scheme: storage_enums::MerchantStorageScheme,
@@ -239,7 +225,8 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve> UpdateTracker<F, PaymentData<F>, api:
 
         let customer_id = payment_data.payment_intent.customer_id.clone();
 
-        payment_data.payment_intent = db
+        payment_data.payment_intent = state
+            .store
             .update_payment_intent(
                 payment_data.payment_intent,
                 storage::PaymentIntentUpdate::ReturnUrlUpdate {
@@ -297,11 +284,12 @@ where
         state: &'a AppState,
         payment_data: &mut PaymentData<F>,
         _storage_scheme: storage_enums::MerchantStorageScheme,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'a, F, api::VerifyRequest, Ctx>,
         Option<api::PaymentMethodData>,
     )> {
-        helpers::make_pm_data(Box::new(self), state, payment_data).await
+        helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await
     }
 
     async fn get_connector<'a>(
@@ -401,6 +389,7 @@ impl PaymentMethodValidate {
             profile_id: Default::default(),
             merchant_decision: Default::default(),
             payment_confirm_source: Default::default(),
+            surcharge_applicable: Default::default(),
             payment_link_id: Default::default(),
             updated_by: storage_scheme.to_string(),
         }
diff --git a/crates/router/src/core/payments/operations/payment_reject.rs b/crates/router/src/core/payments/operations/payment_reject.rs
index 415ab3eccfe7..16d264c001ec 100644
--- a/crates/router/src/core/payments/operations/payment_reject.rs
+++ b/crates/router/src/core/payments/operations/payment_reject.rs
@@ -13,7 +13,6 @@ use crate::{
         payment_methods::PaymentMethodRetrieve,
         payments::{helpers, operations, CustomerDetails, PaymentAddress, PaymentData},
     },
-    db::StorageInterface,
     routes::AppState,
     services,
     types::{
@@ -104,15 +103,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
         )
         .await?;
 
-        let connector_response = db
-            .find_connector_response_by_payment_id_merchant_id_attempt_id(
-                &payment_attempt.payment_id,
-                &payment_attempt.merchant_id,
-                &payment_attempt.attempt_id,
-                storage_scheme,
-            )
-            .await
-            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
         let currency = payment_attempt.currency.get_required_value("currency")?;
         let amount = payment_attempt.amount.into();
 
@@ -147,7 +137,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 refunds: vec![],
                 disputes: vec![],
                 attempts: None,
-                connector_response,
+
                 sessions_token: vec![],
                 card_cvc: None,
                 creds_identifier: None,
@@ -173,7 +163,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
     #[instrument(skip_all)]
     async fn update_trackers<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        state: &'b AppState,
         mut payment_data: PaymentData<F>,
         _customer: Option<domain::Customer>,
         storage_scheme: enums::MerchantStorageScheme,
@@ -210,7 +200,8 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
             updated_by: storage_scheme.to_string(),
         };
 
-        payment_data.payment_intent = db
+        payment_data.payment_intent = state
+            .store
             .update_payment_intent(
                 payment_data.payment_intent,
                 intent_status_update,
@@ -219,7 +210,8 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
             .await
             .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
 
-        payment_data.payment_attempt = db
+        payment_data.payment_attempt = state
+            .store
             .update_payment_attempt_with_attempt_id(
                 payment_data.payment_attempt.clone(),
                 attempt_status_update,
diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs
index 1467da7f816d..b55b0c46f6ad 100644
--- a/crates/router/src/core/payments/operations/payment_response.rs
+++ b/crates/router/src/core/payments/operations/payment_response.rs
@@ -1,10 +1,13 @@
 use std::collections::HashMap;
 
 use async_trait::async_trait;
+use data_models::payments::payment_attempt::PaymentAttempt;
 use error_stack::ResultExt;
 use futures::FutureExt;
 use router_derive;
 use router_env::{instrument, tracing};
+use storage_impl::DataModelExt;
+use tracing_futures::Instrument;
 
 use super::{Operation, PostUpdateTracker};
 use crate::{
@@ -15,8 +18,7 @@ use crate::{
         payments::{types::MultipleCaptureData, PaymentData},
         utils as core_utils,
     },
-    db::StorageInterface,
-    routes::metrics,
+    routes::{metrics, AppState},
     services::RedirectForm,
     types::{
         self, api,
@@ -43,7 +45,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthorizeData
 {
     async fn update_tracker<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         payment_id: &api::PaymentIdType,
         mut payment_data: PaymentData<F>,
         router_data: types::RouterData<
@@ -60,13 +62,13 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthorizeData
             .mandate_id
             .or_else(|| router_data.request.mandate_id.clone());
 
-        payment_data = payment_response_update_tracker(
+        payment_data = Box::pin(payment_response_update_tracker(
             db,
             payment_id,
             payment_data,
             router_data,
             storage_scheme,
-        )
+        ))
         .await?;
 
         Ok(payment_data)
@@ -77,7 +79,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthorizeData
 impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsSyncData> for PaymentResponse {
     async fn update_tracker<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         payment_id: &api::PaymentIdType,
         payment_data: PaymentData<F>,
         router_data: types::RouterData<F, types::PaymentsSyncData, types::PaymentsResponseData>,
@@ -86,8 +88,14 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsSyncData> for
     where
         F: 'b + Send,
     {
-        payment_response_update_tracker(db, payment_id, payment_data, router_data, storage_scheme)
-            .await
+        Box::pin(payment_response_update_tracker(
+            db,
+            payment_id,
+            payment_data,
+            router_data,
+            storage_scheme,
+        ))
+        .await
     }
 }
 
@@ -97,7 +105,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsSessionData>
 {
     async fn update_tracker<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         payment_id: &api::PaymentIdType,
         mut payment_data: PaymentData<F>,
         router_data: types::RouterData<F, types::PaymentsSessionData, types::PaymentsResponseData>,
@@ -106,13 +114,13 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsSessionData>
     where
         F: 'b + Send,
     {
-        payment_data = payment_response_update_tracker(
+        payment_data = Box::pin(payment_response_update_tracker(
             db,
             payment_id,
             payment_data,
             router_data,
             storage_scheme,
-        )
+        ))
         .await?;
 
         Ok(payment_data)
@@ -125,7 +133,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsCaptureData>
 {
     async fn update_tracker<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         payment_id: &api::PaymentIdType,
         mut payment_data: PaymentData<F>,
         router_data: types::RouterData<F, types::PaymentsCaptureData, types::PaymentsResponseData>,
@@ -134,13 +142,13 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsCaptureData>
     where
         F: 'b + Send,
     {
-        payment_data = payment_response_update_tracker(
+        payment_data = Box::pin(payment_response_update_tracker(
             db,
             payment_id,
             payment_data,
             router_data,
             storage_scheme,
-        )
+        ))
         .await?;
 
         Ok(payment_data)
@@ -151,7 +159,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsCaptureData>
 impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsCancelData> for PaymentResponse {
     async fn update_tracker<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         payment_id: &api::PaymentIdType,
         mut payment_data: PaymentData<F>,
         router_data: types::RouterData<F, types::PaymentsCancelData, types::PaymentsResponseData>,
@@ -161,13 +169,13 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsCancelData> f
     where
         F: 'b + Send,
     {
-        payment_data = payment_response_update_tracker(
+        payment_data = Box::pin(payment_response_update_tracker(
             db,
             payment_id,
             payment_data,
             router_data,
             storage_scheme,
-        )
+        ))
         .await?;
 
         Ok(payment_data)
@@ -180,7 +188,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsApproveData>
 {
     async fn update_tracker<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         payment_id: &api::PaymentIdType,
         mut payment_data: PaymentData<F>,
         router_data: types::RouterData<F, types::PaymentsApproveData, types::PaymentsResponseData>,
@@ -190,13 +198,13 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsApproveData>
     where
         F: 'b + Send,
     {
-        payment_data = payment_response_update_tracker(
+        payment_data = Box::pin(payment_response_update_tracker(
             db,
             payment_id,
             payment_data,
             router_data,
             storage_scheme,
-        )
+        ))
         .await?;
 
         Ok(payment_data)
@@ -207,7 +215,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsApproveData>
 impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsRejectData> for PaymentResponse {
     async fn update_tracker<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         payment_id: &api::PaymentIdType,
         mut payment_data: PaymentData<F>,
         router_data: types::RouterData<F, types::PaymentsRejectData, types::PaymentsResponseData>,
@@ -217,13 +225,13 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsRejectData> f
     where
         F: 'b + Send,
     {
-        payment_data = payment_response_update_tracker(
+        payment_data = Box::pin(payment_response_update_tracker(
             db,
             payment_id,
             payment_data,
             router_data,
             storage_scheme,
-        )
+        ))
         .await?;
 
         Ok(payment_data)
@@ -236,7 +244,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::SetupMandateRequestDa
 {
     async fn update_tracker<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         payment_id: &api::PaymentIdType,
         mut payment_data: PaymentData<F>,
         router_data: types::RouterData<
@@ -255,13 +263,13 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::SetupMandateRequestDa
             // .map(api_models::payments::MandateIds::new)
         });
 
-        payment_data = payment_response_update_tracker(
+        payment_data = Box::pin(payment_response_update_tracker(
             db,
             payment_id,
             payment_data,
             router_data,
             storage_scheme,
-        )
+        ))
         .await?;
 
         Ok(payment_data)
@@ -274,7 +282,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::CompleteAuthorizeData
 {
     async fn update_tracker<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        db: &'b AppState,
         payment_id: &api::PaymentIdType,
         payment_data: PaymentData<F>,
         response: types::RouterData<F, types::CompleteAuthorizeData, types::PaymentsResponseData>,
@@ -283,23 +291,26 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::CompleteAuthorizeData
     where
         F: 'b + Send,
     {
-        payment_response_update_tracker(db, payment_id, payment_data, response, storage_scheme)
-            .await
+        Box::pin(payment_response_update_tracker(
+            db,
+            payment_id,
+            payment_data,
+            response,
+            storage_scheme,
+        ))
+        .await
     }
 }
 
 #[instrument(skip_all)]
 async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
-    db: &dyn StorageInterface,
+    state: &AppState,
     _payment_id: &api::PaymentIdType,
     mut payment_data: PaymentData<F>,
     router_data: types::RouterData<F, T, types::PaymentsResponseData>,
     storage_scheme: enums::MerchantStorageScheme,
 ) -> RouterResult<PaymentData<F>> {
-    let (capture_update, mut payment_attempt_update, connector_response_update) = match router_data
-        .response
-        .clone()
-    {
+    let (capture_update, mut payment_attempt_update) = match router_data.response.clone() {
         Err(err) => {
             let (capture_update, attempt_update) = match payment_data.multiple_capture_data {
                 Some(multiple_capture_data) => {
@@ -326,7 +337,7 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
                             match err.status_code {
                                 // marking failure for 2xx because this is genuine payment failure
                                 200..=299 => storage::enums::AttemptStatus::Failure,
-                                _ => payment_data.payment_attempt.status,
+                                _ => router_data.status,
                             }
                         } else {
                             match err.status_code {
@@ -356,14 +367,7 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
                     )
                 }
             };
-            (
-                capture_update,
-                attempt_update,
-                Some(storage::ConnectorResponseUpdate::ErrorUpdate {
-                    connector_name: Some(router_data.connector.clone()),
-                    updated_by: storage_scheme.to_string(),
-                }),
-            )
+            (capture_update, attempt_update)
         }
         Ok(payments_response) => match payments_response {
             types::PaymentsResponseData::PreProcessingResponse {
@@ -394,7 +398,7 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
                     updated_by: storage_scheme.to_string(),
                 };
 
-                (None, Some(payment_attempt_update), None)
+                (None, Some(payment_attempt_update))
             }
             types::PaymentsResponseData::TransactionResponse {
                 resource_id,
@@ -409,8 +413,7 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
                     | types::ResponseId::EncodedData(id) => Some(id),
                 };
 
-                let encoded_data = payment_data.connector_response.encoded_data.clone();
-                let connector_name = router_data.connector.clone();
+                let encoded_data = payment_data.payment_attempt.encoded_data.clone();
 
                 let authentication_data = redirection_data
                     .map(|data| utils::Encode::<RedirectForm>::encode_to_value(&data))
@@ -477,24 +480,16 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
                                 } else {
                                     None
                                 },
+                                surcharge_amount: router_data.request.get_surcharge_amount(),
+                                tax_amount: router_data.request.get_tax_on_surcharge_amount(),
                                 updated_by: storage_scheme.to_string(),
+                                authentication_data,
+                                encoded_data,
                             }),
                         ),
                     };
 
-                let connector_response_update = storage::ConnectorResponseUpdate::ResponseUpdate {
-                    connector_transaction_id,
-                    authentication_data,
-                    encoded_data,
-                    connector_name: Some(connector_name),
-                    updated_by: storage_scheme.to_string(),
-                };
-
-                (
-                    capture_updates,
-                    payment_attempt_update,
-                    Some(connector_response_update),
-                )
+                (capture_updates, payment_attempt_update)
             }
             types::PaymentsResponseData::TransactionUnresolvedResponse {
                 resource_id,
@@ -519,14 +514,13 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
                         connector_response_reference_id,
                         updated_by: storage_scheme.to_string(),
                     }),
-                    None,
                 )
             }
-            types::PaymentsResponseData::SessionResponse { .. } => (None, None, None),
-            types::PaymentsResponseData::SessionTokenResponse { .. } => (None, None, None),
-            types::PaymentsResponseData::TokenizationResponse { .. } => (None, None, None),
-            types::PaymentsResponseData::ConnectorCustomerResponse { .. } => (None, None, None),
-            types::PaymentsResponseData::ThreeDSEnrollmentResponse { .. } => (None, None, None),
+            types::PaymentsResponseData::SessionResponse { .. } => (None, None),
+            types::PaymentsResponseData::SessionTokenResponse { .. } => (None, None),
+            types::PaymentsResponseData::TokenizationResponse { .. } => (None, None),
+            types::PaymentsResponseData::ConnectorCustomerResponse { .. } => (None, None),
+            types::PaymentsResponseData::ThreeDSEnrollmentResponse { .. } => (None, None),
             types::PaymentsResponseData::MultipleCaptureResponse {
                 capture_sync_response_list,
             } => match payment_data.multiple_capture_data {
@@ -535,20 +529,17 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
                         &multiple_capture_data,
                         capture_sync_response_list,
                     )?;
-                    (
-                        Some((multiple_capture_data, capture_update_list)),
-                        None,
-                        None,
-                    )
+                    (Some((multiple_capture_data, capture_update_list)), None)
                 }
-                None => (None, None, None),
+                None => (None, None),
             },
         },
     };
     payment_data.multiple_capture_data = match capture_update {
         Some((mut multiple_capture_data, capture_updates)) => {
             for (capture, capture_update) in capture_updates {
-                let updated_capture = db
+                let updated_capture = state
+                    .store
                     .update_capture_with_capture_id(capture, capture_update, storage_scheme)
                     .await
                     .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
@@ -571,40 +562,44 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
     // Stage 1
 
     let payment_attempt = payment_data.payment_attempt.clone();
-    let connector_response = payment_data.connector_response.clone();
-
-    let payment_attempt_fut = Box::pin(async move {
-        Ok::<_, error_stack::Report<errors::ApiErrorResponse>>(match payment_attempt_update {
-            Some(payment_attempt_update) => db
-                .update_payment_attempt_with_attempt_id(
-                    payment_attempt,
-                    payment_attempt_update,
-                    storage_scheme,
-                )
-                .await
-                .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?,
-            None => payment_attempt,
+
+    let m_db = state.clone().store;
+    let m_payment_attempt_update = payment_attempt_update.clone();
+    let m_payment_attempt = payment_attempt.clone();
+
+    let payment_attempt = payment_attempt_update
+        .map(|payment_attempt_update| {
+            PaymentAttempt::from_storage_model(
+                payment_attempt_update
+                    .to_storage_model()
+                    .apply_changeset(payment_attempt.clone().to_storage_model()),
+            )
         })
-    });
-
-    let connector_response_fut = Box::pin(async move {
-        Ok::<_, error_stack::Report<errors::ApiErrorResponse>>(match connector_response_update {
-            Some(connector_response_update) => db
-                .update_connector_response(
-                    connector_response,
-                    connector_response_update,
-                    storage_scheme,
+        .unwrap_or_else(|| payment_attempt);
+
+    let payment_attempt_fut = tokio::spawn(
+        async move {
+            Box::pin(async move {
+                Ok::<_, error_stack::Report<errors::ApiErrorResponse>>(
+                    match m_payment_attempt_update {
+                        Some(payment_attempt_update) => m_db
+                            .update_payment_attempt_with_attempt_id(
+                                m_payment_attempt,
+                                payment_attempt_update,
+                                storage_scheme,
+                            )
+                            .await
+                            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?,
+                        None => m_payment_attempt,
+                    },
                 )
-                .await
-                .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?,
-            None => connector_response,
-        })
-    });
+            })
+            .await
+        }
+        .in_current_span(),
+    );
 
-    let (payment_attempt, connector_response) =
-        futures::try_join!(payment_attempt_fut, connector_response_fut)?;
     payment_data.payment_attempt = payment_attempt;
-    payment_data.connector_response = connector_response;
 
     let amount_captured = get_total_amount_captured(
         router_data.request,
@@ -612,6 +607,7 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
         router_data.status,
         &payment_data,
     );
+
     let payment_intent_update = match &router_data.response {
         Err(_) => storage::PaymentIntentUpdate::PGStatusUpdate {
             status: payment_data
@@ -629,25 +625,47 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
         },
     };
 
-    let payment_intent_fut = db
-        .update_payment_intent(
-            payment_data.payment_intent.clone(),
-            payment_intent_update,
-            storage_scheme,
-        )
-        .map(|x| x.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound));
+    let m_db = state.clone().store;
+    let m_payment_data_payment_intent = payment_data.payment_intent.clone();
+    let m_payment_intent_update = payment_intent_update.clone();
+    let payment_intent_fut = tokio::spawn(
+        async move {
+            m_db.update_payment_intent(
+                m_payment_data_payment_intent,
+                m_payment_intent_update,
+                storage_scheme,
+            )
+            .map(|x| x.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound))
+            .await
+        }
+        .in_current_span(),
+    );
 
     // When connector requires redirection for mandate creation it can update the connector mandate_id during Psync
-    let mandate_update_fut = mandate::update_connector_mandate_id(
-        db,
-        router_data.merchant_id,
-        payment_data.mandate_id.clone(),
-        router_data.response.clone(),
+    let m_db = state.clone().store;
+    let m_router_data_merchant_id = router_data.merchant_id.clone();
+    let m_payment_data_mandate_id = payment_data.mandate_id.clone();
+    let m_router_data_response = router_data.response.clone();
+    let mandate_update_fut = tokio::spawn(
+        async move {
+            mandate::update_connector_mandate_id(
+                m_db.as_ref(),
+                m_router_data_merchant_id,
+                m_payment_data_mandate_id,
+                m_router_data_response,
+            )
+            .await
+        }
+        .in_current_span(),
     );
 
-    let (payment_intent, _) = futures::try_join!(payment_intent_fut, mandate_update_fut)?;
-    payment_data.payment_intent = payment_intent;
+    let (payment_intent, _, _) = futures::try_join!(
+        utils::flatten_join_error(payment_intent_fut),
+        utils::flatten_join_error(mandate_update_fut),
+        utils::flatten_join_error(payment_attempt_fut)
+    )?;
 
+    payment_data.payment_intent = payment_intent;
     Ok(payment_data)
 }
 
diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs
index b5ed79b2901f..3abde60c2e9b 100644
--- a/crates/router/src/core/payments/operations/payment_session.rs
+++ b/crates/router/src/core/payments/operations/payment_session.rs
@@ -126,20 +126,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
         payment_intent.shipping_address_id = shipping_address.clone().map(|x| x.address_id);
         payment_intent.billing_address_id = billing_address.clone().map(|x| x.address_id);
 
-        let connector_response = db
-            .find_connector_response_by_payment_id_merchant_id_attempt_id(
-                &payment_intent.payment_id,
-                &payment_intent.merchant_id,
-                &payment_attempt.attempt_id,
-                storage_scheme,
-            )
-            .await
-            .map_err(|error| {
-                error
-                    .change_context(errors::ApiErrorResponse::InternalServerError)
-                    .attach_printable("Database error when finding connector response")
-            })?;
-
         let customer_details = payments::CustomerDetails {
             customer_id: payment_intent.customer_id.clone(),
             name: None,
@@ -190,7 +176,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 disputes: vec![],
                 attempts: None,
                 sessions_token: vec![],
-                connector_response,
                 card_cvc: None,
                 creds_identifier,
                 pm_token: None,
@@ -215,7 +200,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
     #[instrument(skip_all)]
     async fn update_trackers<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        state: &'b AppState,
         mut payment_data: PaymentData<F>,
         _customer: Option<domain::Customer>,
         storage_scheme: storage_enums::MerchantStorageScheme,
@@ -232,7 +217,8 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
     {
         let metadata = payment_data.payment_intent.metadata.clone();
         payment_data.payment_intent = match metadata {
-            Some(metadata) => db
+            Some(metadata) => state
+                .store
                 .update_payment_intent(
                     payment_data.payment_intent,
                     storage::PaymentIntentUpdate::MetadataUpdate {
@@ -318,6 +304,7 @@ where
         _state: &'b AppState,
         _payment_data: &mut PaymentData<F>,
         _storage_scheme: storage_enums::MerchantStorageScheme,
+        _merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'b, F, api::PaymentsSessionRequest, Ctx>,
         Option<api::PaymentMethodData>,
@@ -373,10 +360,11 @@ where
         let mut connector_and_supporting_payment_method_type = Vec::new();
 
         filtered_connector_accounts
-            .into_iter()
+            .iter()
             .for_each(|connector_account| {
                 let res = connector_account
                     .payment_methods_enabled
+                    .clone()
                     .unwrap_or_default()
                     .into_iter()
                     .map(|payment_methods_enabled| {
@@ -412,11 +400,7 @@ where
                                 is_invoke_sdk_client && is_sent_in_request
                             })
                             .map(|payment_method_type| {
-                                (
-                                    connector_account.connector_name.to_owned(),
-                                    payment_method_type.payment_method_type,
-                                    connector_account.business_sub_label.to_owned(),
-                                )
+                                (connector_account, payment_method_type.payment_method_type)
                             })
                             .collect::<Vec<_>>()
                     })
@@ -427,14 +411,15 @@ where
         let mut session_connector_data =
             Vec::with_capacity(connector_and_supporting_payment_method_type.len());
 
-        for (connector, payment_method_type, business_sub_label) in
+        for (merchant_connector_account, payment_method_type) in
             connector_and_supporting_payment_method_type
         {
             let connector_type = api::GetToken::from(payment_method_type);
             if let Ok(connector_data) = api::ConnectorData::get_connector_by_name(
                 &state.conf.connectors,
-                &connector,
+                &merchant_connector_account.connector_name.to_string(),
                 connector_type,
+                Some(merchant_connector_account.merchant_connector_id.clone()),
             )
             .map_err(|err| {
                 logger::error!(session_token_error=?err);
@@ -443,7 +428,7 @@ where
                 session_connector_data.push(api::SessionConnectorData {
                     payment_method_type,
                     connector: connector_data,
-                    business_sub_label,
+                    business_sub_label: merchant_connector_account.business_sub_label.clone(),
                 })
             };
         }
diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs
index 227e7e2f90db..17f39d5150bb 100644
--- a/crates/router/src/core/payments/operations/payment_start.rs
+++ b/crates/router/src/core/payments/operations/payment_start.rs
@@ -126,20 +126,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
             ..CustomerDetails::default()
         };
 
-        let connector_response = db
-            .find_connector_response_by_payment_id_merchant_id_attempt_id(
-                &payment_intent.payment_id,
-                &payment_intent.merchant_id,
-                &payment_attempt.attempt_id,
-                storage_scheme,
-            )
-            .await
-            .map_err(|error| {
-                error
-                    .change_context(errors::ApiErrorResponse::InternalServerError)
-                    .attach_printable("Database error when finding connector response")
-            })?;
-
         Ok((
             Box::new(self),
             PaymentData {
@@ -150,7 +136,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 email: None,
                 mandate_id: None,
                 mandate_connector: None,
-                connector_response,
                 setup_mandate: None,
                 token: payment_attempt.payment_token.clone(),
                 address: PaymentAddress {
@@ -189,7 +174,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
     #[instrument(skip_all)]
     async fn update_trackers<'b>(
         &'b self,
-        _db: &dyn StorageInterface,
+        _state: &'b AppState,
         payment_data: PaymentData<F>,
         _customer: Option<domain::Customer>,
         _storage_scheme: storage_enums::MerchantStorageScheme,
@@ -282,6 +267,7 @@ where
         state: &'a AppState,
         payment_data: &mut PaymentData<F>,
         _storage_scheme: storage_enums::MerchantStorageScheme,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'a, F, api::PaymentsStartRequest, Ctx>,
         Option<api::PaymentMethodData>,
@@ -293,7 +279,7 @@ where
             .map(|connector_name| connector_name == *"bluesnap".to_string())
             .unwrap_or(false)
         {
-            helpers::make_pm_data(Box::new(self), state, payment_data).await
+            helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await
         } else {
             Ok((Box::new(self), None))
         }
diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs
index d20830d9bc6b..fb58aeb34e07 100644
--- a/crates/router/src/core/payments/operations/payment_status.rs
+++ b/crates/router/src/core/payments/operations/payment_status.rs
@@ -95,11 +95,12 @@ impl<F: Clone + Send, Ctx: PaymentMethodRetrieve> Domain<F, api::PaymentsRequest
         state: &'a AppState,
         payment_data: &mut PaymentData<F>,
         _storage_scheme: enums::MerchantStorageScheme,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'a, F, api::PaymentsRequest, Ctx>,
         Option<api::PaymentMethodData>,
     )> {
-        helpers::make_pm_data(Box::new(self), state, payment_data).await
+        helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await
     }
 
     #[instrument(skip_all)]
@@ -131,7 +132,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
 {
     async fn update_trackers<'b>(
         &'b self,
-        _db: &dyn StorageInterface,
+        _state: &'b AppState,
         payment_data: PaymentData<F>,
         _customer: Option<domain::Customer>,
         _storage_scheme: enums::MerchantStorageScheme,
@@ -156,7 +157,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
 {
     async fn update_trackers<'b>(
         &'b self,
-        _db: &dyn StorageInterface,
+        _state: &'b AppState,
         payment_data: PaymentData<F>,
         _customer: Option<domain::Customer>,
         _storage_scheme: enums::MerchantStorageScheme,
@@ -225,7 +226,7 @@ async fn get_tracker_for_sync<
     PaymentData<F>,
     Option<CustomerDetails>,
 )> {
-    let (payment_intent, payment_attempt, currency, amount);
+    let (payment_intent, mut payment_attempt, currency, amount);
 
     (payment_intent, payment_attempt) = get_payment_intent_payment_attempt(
         db,
@@ -249,18 +250,7 @@ async fn get_tracker_for_sync<
 
     let payment_id_str = payment_attempt.payment_id.clone();
 
-    let mut connector_response = db
-        .find_connector_response_by_payment_id_merchant_id_attempt_id(
-            &payment_intent.payment_id,
-            &payment_intent.merchant_id,
-            &payment_attempt.attempt_id,
-            storage_scheme,
-        )
-        .await
-        .change_context(errors::ApiErrorResponse::PaymentNotFound)
-        .attach_printable("Database error when finding connector response")?;
-
-    connector_response.encoded_data = request.param.clone();
+    payment_attempt.encoded_data = request.param.clone();
     currency = payment_attempt.currency.get_required_value("currency")?;
     amount = payment_attempt.amount.into();
 
@@ -348,7 +338,7 @@ async fn get_tracker_for_sync<
             format!("Error while retrieving frm_response, merchant_id: {}, payment_id: {payment_id_str}", &merchant_account.merchant_id)
         });
 
-    let contains_encoded_data = connector_response.encoded_data.is_some();
+    let contains_encoded_data = payment_attempt.encoded_data.is_some();
 
     let creds_identifier = request
         .merchant_connector_details
@@ -372,7 +362,6 @@ async fn get_tracker_for_sync<
         PaymentData {
             flow: PhantomData,
             payment_intent,
-            connector_response,
             currency,
             amount,
             email: None,
diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs
index a77ede0e6f6a..53a768f26810 100644
--- a/crates/router/src/core/payments/operations/payment_update.rs
+++ b/crates/router/src/core/payments/operations/payment_update.rs
@@ -106,6 +106,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
             request,
             mandate_type.clone(),
             merchant_account,
+            key_store,
         )
         .await?;
 
@@ -146,8 +147,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
 
         if request.confirm.unwrap_or(false) {
             helpers::validate_customer_id_mandatory_cases(
-                request.shipping.is_some(),
-                request.billing.is_some(),
                 request.setup_future_usage.is_some(),
                 &payment_intent
                     .customer_id
@@ -220,20 +219,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
             )?;
         }
 
-        let connector_response = db
-            .find_connector_response_by_payment_id_merchant_id_attempt_id(
-                &payment_intent.payment_id,
-                &payment_intent.merchant_id,
-                &payment_attempt.attempt_id,
-                storage_scheme,
-            )
-            .await
-            .map_err(|error| {
-                error
-                    .change_context(errors::ApiErrorResponse::InternalServerError)
-                    .attach_printable("Database error when finding connector response")
-            })?;
-
         let mandate_id = request
             .mandate_id
             .as_ref()
@@ -319,6 +304,10 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
         // The operation merges mandate data from both request and payment_attempt
         let setup_mandate = setup_mandate.map(Into::into);
 
+        let surcharge_details = request.surcharge_details.map(|request_surcharge_details| {
+            request_surcharge_details.get_surcharge_details_object(payment_attempt.amount)
+        });
+
         Ok((
             next_operation,
             PaymentData {
@@ -342,7 +331,6 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 refunds: vec![],
                 disputes: vec![],
                 attempts: None,
-                connector_response,
                 sessions_token: vec![],
                 card_cvc: request.card_cvc.clone(),
                 creds_identifier,
@@ -352,7 +340,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
                 ephemeral_key: None,
                 multiple_capture_data: None,
                 redirect_response: None,
-                surcharge_details: None,
+                surcharge_details,
                 frm_message: None,
                 payment_link_data: None,
             },
@@ -396,11 +384,12 @@ impl<F: Clone + Send, Ctx: PaymentMethodRetrieve> Domain<F, api::PaymentsRequest
         state: &'a AppState,
         payment_data: &mut PaymentData<F>,
         _storage_scheme: storage_enums::MerchantStorageScheme,
+        merchant_key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<(
         BoxedOperation<'a, F, api::PaymentsRequest, Ctx>,
         Option<api::PaymentMethodData>,
     )> {
-        helpers::make_pm_data(Box::new(self), state, payment_data).await
+        helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await
     }
 
     #[instrument(skip_all)]
@@ -433,7 +422,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
     #[instrument(skip_all)]
     async fn update_trackers<'b>(
         &'b self,
-        db: &dyn StorageInterface,
+        state: &'b AppState,
         mut payment_data: PaymentData<F>,
         customer: Option<domain::Customer>,
         storage_scheme: storage_enums::MerchantStorageScheme,
@@ -467,7 +456,7 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
             .payment_method_data
             .as_ref()
             .async_map(|payment_method_data| async {
-                helpers::get_additional_payment_data(payment_method_data, db).await
+                helpers::get_additional_payment_data(payment_method_data, &*state.store).await
             })
             .await
             .as_ref()
@@ -482,7 +471,17 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
         let payment_experience = payment_data.payment_attempt.payment_experience;
         let amount_to_capture = payment_data.payment_attempt.amount_to_capture;
         let capture_method = payment_data.payment_attempt.capture_method;
-        payment_data.payment_attempt = db
+
+        let surcharge_amount = payment_data
+            .surcharge_details
+            .as_ref()
+            .map(|surcharge_details| surcharge_details.surcharge_amount);
+        let tax_amount = payment_data
+            .surcharge_details
+            .as_ref()
+            .map(|surcharge_details| surcharge_details.tax_on_surcharge_amount);
+        payment_data.payment_attempt = state
+            .store
             .update_payment_attempt_with_attempt_id(
                 payment_data.payment_attempt,
                 storage::PaymentAttemptUpdate::Update {
@@ -498,6 +497,8 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
                     business_sub_label,
                     amount_to_capture,
                     capture_method,
+                    surcharge_amount,
+                    tax_amount,
                     updated_by: storage_scheme.to_string(),
                 },
                 storage_scheme,
@@ -541,7 +542,8 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
         let order_details = payment_data.payment_intent.order_details.clone();
         let metadata = payment_data.payment_intent.metadata.clone();
 
-        payment_data.payment_intent = db
+        payment_data.payment_intent = state
+            .store
             .update_payment_intent(
                 payment_data.payment_intent,
                 storage::PaymentIntentUpdate::Update {
diff --git a/crates/router/src/core/payments/retry.rs b/crates/router/src/core/payments/retry.rs
new file mode 100644
index 000000000000..376b9048c856
--- /dev/null
+++ b/crates/router/src/core/payments/retry.rs
@@ -0,0 +1,581 @@
+use std::{str::FromStr, vec::IntoIter};
+
+use diesel_models::enums as storage_enums;
+use error_stack::{IntoReport, ResultExt};
+use router_env::{
+    logger,
+    tracing::{self, instrument},
+};
+
+use crate::{
+    core::{
+        errors::{self, RouterResult, StorageErrorExt},
+        payment_methods::PaymentMethodRetrieve,
+        payments::{
+            self,
+            flows::{ConstructFlowSpecificData, Feature},
+            operations,
+        },
+    },
+    db::StorageInterface,
+    routes,
+    routes::{app, metrics},
+    services::{self, RedirectForm},
+    types,
+    types::{api, domain, storage},
+    utils,
+};
+
+#[instrument(skip_all)]
+#[allow(clippy::too_many_arguments)]
+pub async fn do_gsm_actions<F, ApiRequest, FData, Ctx>(
+    state: &app::AppState,
+    payment_data: &mut payments::PaymentData<F>,
+    mut connectors: IntoIter<api::ConnectorData>,
+    original_connector_data: api::ConnectorData,
+    mut router_data: types::RouterData<F, FData, types::PaymentsResponseData>,
+    merchant_account: &domain::MerchantAccount,
+    key_store: &domain::MerchantKeyStore,
+    operation: &operations::BoxedOperation<'_, F, ApiRequest, Ctx>,
+    customer: &Option<domain::Customer>,
+    validate_result: &operations::ValidateResult<'_>,
+    schedule_time: Option<time::PrimitiveDateTime>,
+) -> RouterResult<types::RouterData<F, FData, types::PaymentsResponseData>>
+where
+    F: Clone + Send + Sync,
+    FData: Send + Sync,
+    payments::PaymentResponse: operations::Operation<F, FData, Ctx>,
+
+    payments::PaymentData<F>: ConstructFlowSpecificData<F, FData, types::PaymentsResponseData>,
+    types::RouterData<F, FData, types::PaymentsResponseData>: Feature<F, FData>,
+    dyn api::Connector: services::api::ConnectorIntegration<F, FData, types::PaymentsResponseData>,
+    Ctx: PaymentMethodRetrieve,
+{
+    let mut retries = None;
+
+    metrics::AUTO_RETRY_ELIGIBLE_REQUEST_COUNT.add(&metrics::CONTEXT, 1, &[]);
+
+    let mut initial_gsm = get_gsm(state, &router_data).await;
+
+    //Check if step-up to threeDS is possible and merchant has enabled
+    let step_up_possible = initial_gsm
+        .clone()
+        .map(|gsm| gsm.step_up_possible)
+        .unwrap_or(false);
+    let is_no_three_ds_payment = matches!(
+        payment_data.payment_attempt.authentication_type,
+        Some(storage_enums::AuthenticationType::NoThreeDs)
+    );
+    let should_step_up = if step_up_possible && is_no_three_ds_payment {
+        is_step_up_enabled_for_merchant_connector(
+            state,
+            &merchant_account.merchant_id,
+            original_connector_data.connector_name,
+        )
+        .await
+    } else {
+        false
+    };
+
+    if should_step_up {
+        router_data = do_retry(
+            &state.clone(),
+            original_connector_data,
+            operation,
+            customer,
+            merchant_account,
+            key_store,
+            payment_data,
+            router_data,
+            validate_result,
+            schedule_time,
+            true,
+        )
+        .await?;
+    }
+    // Step up is not applicable so proceed with auto retries flow
+    else {
+        loop {
+            // Use initial_gsm for first time alone
+            let gsm = match initial_gsm.as_ref() {
+                Some(gsm) => Some(gsm.clone()),
+                None => get_gsm(state, &router_data).await,
+            };
+
+            match get_gsm_decision(gsm) {
+                api_models::gsm::GsmDecision::Retry => {
+                    retries = get_retries(state, retries, &merchant_account.merchant_id).await;
+
+                    if retries.is_none() || retries == Some(0) {
+                        metrics::AUTO_RETRY_EXHAUSTED_COUNT.add(&metrics::CONTEXT, 1, &[]);
+                        logger::info!("retries exhausted for auto_retry payment");
+                        break;
+                    }
+
+                    if connectors.len() == 0 {
+                        logger::info!("connectors exhausted for auto_retry payment");
+                        metrics::AUTO_RETRY_EXHAUSTED_COUNT.add(&metrics::CONTEXT, 1, &[]);
+                        break;
+                    }
+
+                    let connector = super::get_connector_data(&mut connectors)?;
+
+                    router_data = do_retry(
+                        &state.clone(),
+                        connector,
+                        operation,
+                        customer,
+                        merchant_account,
+                        key_store,
+                        payment_data,
+                        router_data,
+                        validate_result,
+                        schedule_time,
+                        //this is an auto retry payment, but not step-up
+                        false,
+                    )
+                    .await?;
+
+                    retries = retries.map(|i| i - 1);
+                }
+                api_models::gsm::GsmDecision::Requeue => {
+                    Err(errors::ApiErrorResponse::NotImplemented {
+                        message: errors::api_error_response::NotImplementedMessage::Reason(
+                            "Requeue not implemented".to_string(),
+                        ),
+                    })
+                    .into_report()?
+                }
+                api_models::gsm::GsmDecision::DoDefault => break,
+            }
+            initial_gsm = None;
+        }
+    }
+    Ok(router_data)
+}
+
+#[instrument(skip_all)]
+pub async fn is_step_up_enabled_for_merchant_connector(
+    state: &app::AppState,
+    merchant_id: &str,
+    connector_name: types::Connector,
+) -> bool {
+    let key = format!("step_up_enabled_{merchant_id}");
+    let db = &*state.store;
+    db.find_config_by_key_unwrap_or(key.as_str(), Some("[]".to_string()))
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .and_then(|step_up_config| {
+            serde_json::from_str::<Vec<types::Connector>>(&step_up_config.config)
+                .into_report()
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Step-up config parsing failed")
+        })
+        .map_err(|err| {
+            logger::error!(step_up_config_error=?err);
+        })
+        .ok()
+        .map(|connectors_enabled| connectors_enabled.contains(&connector_name))
+        .unwrap_or(false)
+}
+
+#[instrument(skip_all)]
+pub async fn get_retries(
+    state: &app::AppState,
+    retries: Option<i32>,
+    merchant_id: &str,
+) -> Option<i32> {
+    match retries {
+        Some(retries) => Some(retries),
+        None => {
+            let key = format!("max_auto_retries_enabled_{merchant_id}");
+            let db = &*state.store;
+            db.find_config_by_key(key.as_str())
+                .await
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .and_then(|retries_config| {
+                    retries_config
+                        .config
+                        .parse::<i32>()
+                        .into_report()
+                        .change_context(errors::ApiErrorResponse::InternalServerError)
+                        .attach_printable("Retries config parsing failed")
+                })
+                .map_err(|err| {
+                    logger::error!(retries_error=?err);
+                    None::<i32>
+                })
+                .ok()
+        }
+    }
+}
+
+#[instrument(skip_all)]
+pub async fn get_gsm<F, FData>(
+    state: &app::AppState,
+    router_data: &types::RouterData<F, FData, types::PaymentsResponseData>,
+) -> Option<storage::gsm::GatewayStatusMap> {
+    let error_response = router_data.response.as_ref().err();
+    let error_code = error_response.map(|err| err.code.to_owned());
+    let error_message = error_response.map(|err| err.message.to_owned());
+    let get_gsm = || async {
+        let connector_name = router_data.connector.to_string();
+        let flow = get_flow_name::<F>()?;
+        state.store.find_gsm_rule(
+                connector_name.clone(),
+                flow.clone(),
+                "sub_flow".to_string(),
+                error_code.clone().unwrap_or_default(), // TODO: make changes in connector to get a mandatory code in case of success or error response
+                error_message.clone().unwrap_or_default(),
+            )
+            .await
+            .map_err(|err| {
+                if err.current_context().is_db_not_found() {
+                    logger::warn!(
+                        "GSM miss for connector - {}, flow - {}, error_code - {:?}, error_message - {:?}",
+                        connector_name,
+                        flow,
+                        error_code,
+                        error_message
+                    );
+                    metrics::AUTO_RETRY_GSM_MISS_COUNT.add(&metrics::CONTEXT, 1, &[]);
+                } else {
+                    metrics::AUTO_RETRY_GSM_FETCH_FAILURE_COUNT.add(&metrics::CONTEXT, 1, &[]);
+                };
+                err.change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("failed to fetch decision from gsm")
+            })
+    };
+    get_gsm()
+        .await
+        .map_err(|err| {
+            // warn log should suffice here because we are not propagating this error
+            logger::warn!(get_gsm_decision_fetch_error=?err, "error fetching gsm decision");
+            err
+        })
+        .ok()
+}
+
+#[instrument(skip_all)]
+pub fn get_gsm_decision(
+    option_gsm: Option<storage::gsm::GatewayStatusMap>,
+) -> api_models::gsm::GsmDecision {
+    let option_gsm_decision = option_gsm
+            .and_then(|gsm| {
+                api_models::gsm::GsmDecision::from_str(gsm.decision.as_str())
+                    .into_report()
+                    .map_err(|err| {
+                        let api_error = err.change_context(errors::ApiErrorResponse::InternalServerError)
+                            .attach_printable("gsm decision parsing failed");
+                        logger::warn!(get_gsm_decision_parse_error=?api_error, "error fetching gsm decision");
+                        api_error
+                    })
+                    .ok()
+            });
+
+    if option_gsm_decision.is_some() {
+        metrics::AUTO_RETRY_GSM_MATCH_COUNT.add(&metrics::CONTEXT, 1, &[]);
+    }
+    option_gsm_decision.unwrap_or_default()
+}
+
+#[inline]
+fn get_flow_name<F>() -> RouterResult<String> {
+    Ok(std::any::type_name::<F>()
+        .to_string()
+        .rsplit("::")
+        .next()
+        .ok_or(errors::ApiErrorResponse::InternalServerError)
+        .into_report()
+        .attach_printable("Flow stringify failed")?
+        .to_string())
+}
+
+#[allow(clippy::too_many_arguments)]
+#[instrument(skip_all)]
+pub async fn do_retry<F, ApiRequest, FData, Ctx>(
+    state: &routes::AppState,
+    connector: api::ConnectorData,
+    operation: &operations::BoxedOperation<'_, F, ApiRequest, Ctx>,
+    customer: &Option<domain::Customer>,
+    merchant_account: &domain::MerchantAccount,
+    key_store: &domain::MerchantKeyStore,
+    payment_data: &mut payments::PaymentData<F>,
+    router_data: types::RouterData<F, FData, types::PaymentsResponseData>,
+    validate_result: &operations::ValidateResult<'_>,
+    schedule_time: Option<time::PrimitiveDateTime>,
+    is_step_up: bool,
+) -> RouterResult<types::RouterData<F, FData, types::PaymentsResponseData>>
+where
+    F: Clone + Send + Sync,
+    FData: Send + Sync,
+    payments::PaymentResponse: operations::Operation<F, FData, Ctx>,
+
+    payments::PaymentData<F>: ConstructFlowSpecificData<F, FData, types::PaymentsResponseData>,
+    types::RouterData<F, FData, types::PaymentsResponseData>: Feature<F, FData>,
+    dyn api::Connector: services::api::ConnectorIntegration<F, FData, types::PaymentsResponseData>,
+    Ctx: PaymentMethodRetrieve,
+{
+    metrics::AUTO_RETRY_PAYMENT_COUNT.add(&metrics::CONTEXT, 1, &[]);
+
+    modify_trackers(
+        state,
+        connector.connector_name.to_string(),
+        payment_data,
+        merchant_account.storage_scheme,
+        router_data,
+        is_step_up,
+    )
+    .await?;
+
+    payments::call_connector_service(
+        state,
+        merchant_account,
+        key_store,
+        connector,
+        operation,
+        payment_data,
+        customer,
+        payments::CallConnectorAction::Trigger,
+        validate_result,
+        schedule_time,
+        api::HeaderPayload::default(),
+    )
+    .await
+}
+
+#[instrument(skip_all)]
+pub async fn modify_trackers<F, FData>(
+    state: &routes::AppState,
+    connector: String,
+    payment_data: &mut payments::PaymentData<F>,
+    storage_scheme: storage_enums::MerchantStorageScheme,
+    router_data: types::RouterData<F, FData, types::PaymentsResponseData>,
+    is_step_up: bool,
+) -> RouterResult<()>
+where
+    F: Clone + Send,
+    FData: Send,
+{
+    let new_attempt_count = payment_data.payment_intent.attempt_count + 1;
+    let new_payment_attempt = make_new_payment_attempt(
+        connector,
+        payment_data.payment_attempt.clone(),
+        new_attempt_count,
+        is_step_up,
+    );
+
+    let db = &*state.store;
+
+    match router_data.response {
+        Ok(types::PaymentsResponseData::TransactionResponse {
+            resource_id,
+            connector_metadata,
+            redirection_data,
+            ..
+        }) => {
+            let encoded_data = payment_data.payment_attempt.encoded_data.clone();
+
+            let authentication_data = redirection_data
+                .map(|data| utils::Encode::<RedirectForm>::encode_to_value(&data))
+                .transpose()
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Could not parse the connector response")?;
+
+            db.update_payment_attempt_with_attempt_id(
+                payment_data.payment_attempt.clone(),
+                storage::PaymentAttemptUpdate::ResponseUpdate {
+                    status: router_data.status,
+                    connector: None,
+                    connector_transaction_id: match resource_id {
+                        types::ResponseId::NoResponseId => None,
+                        types::ResponseId::ConnectorTransactionId(id)
+                        | types::ResponseId::EncodedData(id) => Some(id),
+                    },
+                    connector_response_reference_id: payment_data
+                        .payment_attempt
+                        .connector_response_reference_id
+                        .clone(),
+                    authentication_type: None,
+                    payment_method_id: Some(router_data.payment_method_id),
+                    mandate_id: payment_data
+                        .mandate_id
+                        .clone()
+                        .map(|mandate| mandate.mandate_id),
+                    connector_metadata,
+                    payment_token: None,
+                    error_code: None,
+                    error_message: None,
+                    error_reason: None,
+                    amount_capturable: if router_data.status.is_terminal_status() {
+                        Some(0)
+                    } else {
+                        None
+                    },
+                    surcharge_amount: None,
+                    tax_amount: None,
+                    updated_by: storage_scheme.to_string(),
+                    authentication_data,
+                    encoded_data,
+                },
+                storage_scheme,
+            )
+            .await
+            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
+        }
+        Ok(_) => {
+            logger::error!("unexpected response: this response was not expected in Retry flow");
+            return Ok(());
+        }
+        Err(error_response) => {
+            db.update_payment_attempt_with_attempt_id(
+                payment_data.payment_attempt.clone(),
+                storage::PaymentAttemptUpdate::ErrorUpdate {
+                    connector: None,
+                    error_code: Some(Some(error_response.code)),
+                    error_message: Some(Some(error_response.message)),
+                    status: storage_enums::AttemptStatus::Failure,
+                    error_reason: Some(error_response.reason),
+                    amount_capturable: Some(0),
+                    updated_by: storage_scheme.to_string(),
+                },
+                storage_scheme,
+            )
+            .await
+            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
+        }
+    }
+
+    let payment_attempt = db
+        .insert_payment_attempt(new_payment_attempt, storage_scheme)
+        .await
+        .to_duplicate_response(errors::ApiErrorResponse::DuplicatePayment {
+            payment_id: payment_data.payment_intent.payment_id.clone(),
+        })?;
+
+    // update payment_attempt, connector_response and payment_intent in payment_data
+    payment_data.payment_attempt = payment_attempt;
+
+    payment_data.payment_intent = db
+        .update_payment_intent(
+            payment_data.payment_intent.clone(),
+            storage::PaymentIntentUpdate::PaymentAttemptAndAttemptCountUpdate {
+                active_attempt_id: payment_data.payment_attempt.attempt_id.clone(),
+                attempt_count: new_attempt_count,
+                updated_by: storage_scheme.to_string(),
+            },
+            storage_scheme,
+        )
+        .await
+        .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
+
+    Ok(())
+}
+
+#[instrument(skip_all)]
+pub fn make_new_payment_attempt(
+    connector: String,
+    old_payment_attempt: storage::PaymentAttempt,
+    new_attempt_count: i16,
+    is_step_up: bool,
+) -> storage::PaymentAttemptNew {
+    let created_at @ modified_at @ last_synced = Some(common_utils::date_time::now());
+    storage::PaymentAttemptNew {
+        connector: Some(connector),
+        attempt_id: utils::get_payment_attempt_id(
+            &old_payment_attempt.payment_id,
+            new_attempt_count,
+        ),
+        payment_id: old_payment_attempt.payment_id,
+        merchant_id: old_payment_attempt.merchant_id,
+        status: old_payment_attempt.status,
+        amount: old_payment_attempt.amount,
+        currency: old_payment_attempt.currency,
+        save_to_locker: old_payment_attempt.save_to_locker,
+
+        offer_amount: old_payment_attempt.offer_amount,
+        surcharge_amount: old_payment_attempt.surcharge_amount,
+        tax_amount: old_payment_attempt.tax_amount,
+        payment_method_id: old_payment_attempt.payment_method_id,
+        payment_method: old_payment_attempt.payment_method,
+        payment_method_type: old_payment_attempt.payment_method_type,
+        capture_method: old_payment_attempt.capture_method,
+        capture_on: old_payment_attempt.capture_on,
+        confirm: old_payment_attempt.confirm,
+        authentication_type: if is_step_up {
+            Some(storage_enums::AuthenticationType::ThreeDs)
+        } else {
+            old_payment_attempt.authentication_type
+        },
+
+        amount_to_capture: old_payment_attempt.amount_to_capture,
+        mandate_id: old_payment_attempt.mandate_id,
+        browser_info: old_payment_attempt.browser_info,
+        payment_token: old_payment_attempt.payment_token,
+
+        created_at,
+        modified_at,
+        last_synced,
+        ..storage::PaymentAttemptNew::default()
+    }
+}
+
+pub async fn config_should_call_gsm(db: &dyn StorageInterface, merchant_id: &String) -> bool {
+    let config = db
+        .find_config_by_key_unwrap_or(
+            format!("should_call_gsm_{}", merchant_id).as_str(),
+            Some("false".to_string()),
+        )
+        .await;
+    match config {
+        Ok(conf) => conf.config == "true",
+        Err(err) => {
+            logger::error!("{err}");
+            false
+        }
+    }
+}
+
+pub trait GsmValidation<F: Send + Clone + Sync, FData: Send + Sync, Resp> {
+    // TODO : move this function to appropriate place later.
+    fn should_call_gsm(&self) -> bool;
+}
+
+impl<F: Send + Clone + Sync, FData: Send + Sync>
+    GsmValidation<F, FData, types::PaymentsResponseData>
+    for types::RouterData<F, FData, types::PaymentsResponseData>
+{
+    #[inline(always)]
+    fn should_call_gsm(&self) -> bool {
+        if self.response.is_err() {
+            true
+        } else {
+            match self.status {
+                storage_enums::AttemptStatus::Started
+                | storage_enums::AttemptStatus::AuthenticationPending
+                | storage_enums::AttemptStatus::AuthenticationSuccessful
+                | storage_enums::AttemptStatus::Authorized
+                | storage_enums::AttemptStatus::Charged
+                | storage_enums::AttemptStatus::Authorizing
+                | storage_enums::AttemptStatus::CodInitiated
+                | storage_enums::AttemptStatus::Voided
+                | storage_enums::AttemptStatus::VoidInitiated
+                | storage_enums::AttemptStatus::CaptureInitiated
+                | storage_enums::AttemptStatus::RouterDeclined
+                | storage_enums::AttemptStatus::VoidFailed
+                | storage_enums::AttemptStatus::AutoRefunded
+                | storage_enums::AttemptStatus::CaptureFailed
+                | storage_enums::AttemptStatus::PartialCharged
+                | storage_enums::AttemptStatus::Pending
+                | storage_enums::AttemptStatus::PaymentMethodAwaited
+                | storage_enums::AttemptStatus::ConfirmationAwaited
+                | storage_enums::AttemptStatus::Unresolved
+                | storage_enums::AttemptStatus::DeviceDataCollectionPending => false,
+
+                storage_enums::AttemptStatus::AuthenticationFailed
+                | storage_enums::AttemptStatus::AuthorizationFailed
+                | storage_enums::AttemptStatus::Failure => true,
+            }
+        }
+    }
+}
diff --git a/crates/router/src/core/payments/routing.rs b/crates/router/src/core/payments/routing.rs
new file mode 100644
index 000000000000..3b89d4e38e4e
--- /dev/null
+++ b/crates/router/src/core/payments/routing.rs
@@ -0,0 +1,998 @@
+mod transformers;
+
+use std::{
+    collections::hash_map,
+    hash::{Hash, Hasher},
+    sync::Arc,
+};
+
+use api_models::{
+    admin as admin_api,
+    enums::{self as api_enums, CountryAlpha2},
+    routing::ConnectorSelection,
+};
+use common_utils::static_cache::StaticCache;
+use diesel_models::enums as storage_enums;
+use error_stack::{IntoReport, ResultExt};
+use euclid::{
+    backend::{self, inputs as dsl_inputs, EuclidBackend},
+    dssa::graph::{self as euclid_graph, Memoization},
+    enums as euclid_enums,
+    frontend::ast,
+};
+use kgraph_utils::{
+    mca as mca_graph,
+    transformers::{IntoContext, IntoDirValue},
+};
+use masking::PeekInterface;
+use rand::{
+    distributions::{self, Distribution},
+    SeedableRng,
+};
+use rustc_hash::FxHashMap;
+
+#[cfg(not(feature = "business_profile_routing"))]
+use crate::utils::StringExt;
+use crate::{
+    core::{
+        errors as oss_errors, errors, payments as payments_oss, routing::helpers as routing_helpers,
+    },
+    logger,
+    types::{
+        api, api::routing as routing_types, domain, storage as oss_storage,
+        transformers::ForeignInto,
+    },
+    utils::{OptionExt, ValueExt},
+    AppState,
+};
+
+pub(super) enum CachedAlgorithm {
+    Single(Box<routing_types::RoutableConnectorChoice>),
+    Priority(Vec<routing_types::RoutableConnectorChoice>),
+    VolumeSplit(Vec<routing_types::ConnectorVolumeSplit>),
+    Advanced(backend::VirInterpreterBackend<ConnectorSelection>),
+}
+
+pub struct SessionFlowRoutingInput<'a> {
+    pub state: &'a AppState,
+    pub country: Option<CountryAlpha2>,
+    pub key_store: &'a domain::MerchantKeyStore,
+    pub merchant_account: &'a domain::MerchantAccount,
+    pub payment_attempt: &'a oss_storage::PaymentAttempt,
+    pub payment_intent: &'a oss_storage::PaymentIntent,
+    pub chosen: Vec<api::SessionConnectorData>,
+}
+
+pub struct SessionRoutingPmTypeInput<'a> {
+    state: &'a AppState,
+    key_store: &'a domain::MerchantKeyStore,
+    merchant_last_modified: i64,
+    attempt_id: &'a str,
+    routing_algorithm: &'a MerchantAccountRoutingAlgorithm,
+    backend_input: dsl_inputs::BackendInput,
+    allowed_connectors: FxHashMap<String, api::GetToken>,
+    #[cfg(any(
+        feature = "business_profile_routing",
+        feature = "profile_specific_fallback_routing"
+    ))]
+    profile_id: Option<String>,
+}
+static ROUTING_CACHE: StaticCache<CachedAlgorithm> = StaticCache::new();
+static KGRAPH_CACHE: StaticCache<euclid_graph::KnowledgeGraph<'_>> = StaticCache::new();
+
+type RoutingResult<O> = oss_errors::CustomResult<O, errors::RoutingError>;
+
+#[derive(Debug, serde::Serialize, serde::Deserialize)]
+#[serde(untagged)]
+enum MerchantAccountRoutingAlgorithm {
+    V1(routing_types::RoutingAlgorithmRef),
+}
+
+impl Default for MerchantAccountRoutingAlgorithm {
+    fn default() -> Self {
+        Self::V1(routing_types::RoutingAlgorithmRef::default())
+    }
+}
+
+pub fn make_dsl_input<F>(
+    payment_data: &payments_oss::PaymentData<F>,
+) -> RoutingResult<dsl_inputs::BackendInput>
+where
+    F: Clone,
+{
+    let mandate_data = dsl_inputs::MandateData {
+        mandate_acceptance_type: payment_data
+            .setup_mandate
+            .as_ref()
+            .and_then(|mandate_data| {
+                mandate_data
+                    .customer_acceptance
+                    .clone()
+                    .map(|cat| match cat.acceptance_type {
+                        data_models::mandates::AcceptanceType::Online => {
+                            euclid_enums::MandateAcceptanceType::Online
+                        }
+                        data_models::mandates::AcceptanceType::Offline => {
+                            euclid_enums::MandateAcceptanceType::Offline
+                        }
+                    })
+            }),
+        mandate_type: payment_data
+            .setup_mandate
+            .as_ref()
+            .and_then(|mandate_data| {
+                mandate_data.mandate_type.clone().map(|mt| match mt {
+                    data_models::mandates::MandateDataType::SingleUse(_) => {
+                        euclid_enums::MandateType::SingleUse
+                    }
+                    data_models::mandates::MandateDataType::MultiUse(_) => {
+                        euclid_enums::MandateType::MultiUse
+                    }
+                })
+            }),
+        payment_type: Some(payment_data.setup_mandate.clone().map_or_else(
+            || euclid_enums::PaymentType::NonMandate,
+            |_| euclid_enums::PaymentType::SetupMandate,
+        )),
+    };
+    let payment_method_input = dsl_inputs::PaymentMethodInput {
+        payment_method: payment_data.payment_attempt.payment_method,
+        payment_method_type: payment_data.payment_attempt.payment_method_type,
+        card_network: payment_data
+            .payment_method_data
+            .as_ref()
+            .and_then(|pm_data| match pm_data {
+                api::PaymentMethodData::Card(card) => card.card_network.clone(),
+
+                _ => None,
+            }),
+    };
+
+    let payment_input = dsl_inputs::PaymentInput {
+        amount: payment_data.payment_intent.amount,
+        card_bin: payment_data
+            .payment_method_data
+            .as_ref()
+            .and_then(|pm_data| match pm_data {
+                api::PaymentMethodData::Card(card) => {
+                    Some(card.card_number.peek().chars().take(6).collect())
+                }
+                _ => None,
+            }),
+        currency: payment_data.currency,
+        authentication_type: payment_data.payment_attempt.authentication_type,
+        capture_method: payment_data
+            .payment_attempt
+            .capture_method
+            .and_then(|cm| cm.foreign_into()),
+        business_country: payment_data
+            .payment_intent
+            .business_country
+            .map(api_enums::Country::from_alpha2),
+        billing_country: payment_data
+            .address
+            .billing
+            .as_ref()
+            .and_then(|bic| bic.address.as_ref())
+            .and_then(|add| add.country)
+            .map(api_enums::Country::from_alpha2),
+        business_label: payment_data.payment_intent.business_label.clone(),
+        setup_future_usage: payment_data.payment_intent.setup_future_usage,
+    };
+
+    let metadata = payment_data
+        .payment_intent
+        .metadata
+        .clone()
+        .map(|val| val.parse_value("routing_parameters"))
+        .transpose()
+        .change_context(errors::RoutingError::MetadataParsingError)
+        .attach_printable("Unable to parse routing_parameters from metadata of payment_intent")
+        .unwrap_or_else(|err| {
+            logger::error!(error=?err);
+            None
+        });
+
+    Ok(dsl_inputs::BackendInput {
+        metadata,
+        payment: payment_input,
+        payment_method: payment_method_input,
+        mandate: mandate_data,
+    })
+}
+
+pub async fn perform_static_routing_v1<F: Clone>(
+    state: &AppState,
+    merchant_id: &str,
+    algorithm_ref: routing_types::RoutingAlgorithmRef,
+    payment_data: &mut payments_oss::PaymentData<F>,
+) -> RoutingResult<Vec<routing_types::RoutableConnectorChoice>> {
+    let algorithm_id = if let Some(id) = algorithm_ref.algorithm_id {
+        id
+    } else {
+        let fallback_config = routing_helpers::get_merchant_default_config(
+            &*state.clone().store,
+            #[cfg(not(feature = "profile_specific_fallback_routing"))]
+            merchant_id,
+            #[cfg(feature = "profile_specific_fallback_routing")]
+            {
+                payment_data
+                    .payment_intent
+                    .profile_id
+                    .as_ref()
+                    .get_required_value("profile_id")
+                    .change_context(errors::RoutingError::ProfileIdMissing)?
+            },
+        )
+        .await
+        .change_context(errors::RoutingError::FallbackConfigFetchFailed)?;
+
+        return Ok(fallback_config);
+    };
+    let key = ensure_algorithm_cached_v1(
+        state,
+        merchant_id,
+        algorithm_ref.timestamp,
+        &algorithm_id,
+        #[cfg(feature = "business_profile_routing")]
+        payment_data.payment_intent.profile_id.clone(),
+    )
+    .await?;
+    let cached_algorithm: Arc<CachedAlgorithm> = ROUTING_CACHE
+        .retrieve(&key)
+        .into_report()
+        .change_context(errors::RoutingError::CacheMiss)
+        .attach_printable("Unable to retrieve cached routing algorithm even after refresh")?;
+
+    Ok(match cached_algorithm.as_ref() {
+        CachedAlgorithm::Single(conn) => vec![(**conn).clone()],
+
+        CachedAlgorithm::Priority(plist) => plist.clone(),
+
+        CachedAlgorithm::VolumeSplit(splits) => perform_volume_split(splits.to_vec(), None)
+            .change_context(errors::RoutingError::ConnectorSelectionFailed)?,
+
+        CachedAlgorithm::Advanced(interpreter) => {
+            let backend_input = make_dsl_input(payment_data)?;
+
+            execute_dsl_and_get_connector_v1(backend_input, interpreter)?
+        }
+    })
+}
+
+async fn ensure_algorithm_cached_v1(
+    state: &AppState,
+    merchant_id: &str,
+    timestamp: i64,
+    algorithm_id: &str,
+    #[cfg(feature = "business_profile_routing")] profile_id: Option<String>,
+) -> RoutingResult<String> {
+    #[cfg(feature = "business_profile_routing")]
+    let key = {
+        let profile_id = profile_id
+            .clone()
+            .get_required_value("profile_id")
+            .change_context(errors::RoutingError::ProfileIdMissing)?;
+
+        format!("routing_config_{merchant_id}_{profile_id}")
+    };
+
+    #[cfg(not(feature = "business_profile_routing"))]
+    let key = format!("dsl_{merchant_id}");
+
+    let present = ROUTING_CACHE
+        .present(&key)
+        .into_report()
+        .change_context(errors::RoutingError::DslCachePoisoned)
+        .attach_printable("Error checking presence of DSL")?;
+
+    let expired = ROUTING_CACHE
+        .expired(&key, timestamp)
+        .into_report()
+        .change_context(errors::RoutingError::DslCachePoisoned)
+        .attach_printable("Error checking expiry of DSL in cache")?;
+
+    if !present || expired {
+        refresh_routing_cache_v1(
+            state,
+            key.clone(),
+            algorithm_id,
+            timestamp,
+            #[cfg(feature = "business_profile_routing")]
+            profile_id,
+        )
+        .await?;
+    };
+
+    Ok(key)
+}
+
+pub fn perform_straight_through_routing<F: Clone>(
+    algorithm: &routing_types::StraightThroughAlgorithm,
+    payment_data: &payments_oss::PaymentData<F>,
+) -> RoutingResult<(Vec<routing_types::RoutableConnectorChoice>, bool)> {
+    Ok(match algorithm {
+        routing_types::StraightThroughAlgorithm::Single(conn) => (
+            vec![(**conn).clone()],
+            payment_data.creds_identifier.is_none(),
+        ),
+
+        routing_types::StraightThroughAlgorithm::Priority(conns) => (conns.clone(), true),
+
+        routing_types::StraightThroughAlgorithm::VolumeSplit(splits) => (
+            perform_volume_split(splits.to_vec(), None)
+                .change_context(errors::RoutingError::ConnectorSelectionFailed)
+                .attach_printable(
+                    "Volume Split connector selection error in straight through routing",
+                )?,
+            true,
+        ),
+    })
+}
+
+fn execute_dsl_and_get_connector_v1(
+    backend_input: dsl_inputs::BackendInput,
+    interpreter: &backend::VirInterpreterBackend<ConnectorSelection>,
+) -> RoutingResult<Vec<routing_types::RoutableConnectorChoice>> {
+    let routing_output: routing_types::RoutingAlgorithm = interpreter
+        .execute(backend_input)
+        .map(|out| out.connector_selection.foreign_into())
+        .into_report()
+        .change_context(errors::RoutingError::DslExecutionError)?;
+
+    Ok(match routing_output {
+        routing_types::RoutingAlgorithm::Priority(plist) => plist,
+
+        routing_types::RoutingAlgorithm::VolumeSplit(splits) => perform_volume_split(splits, None)
+            .change_context(errors::RoutingError::DslFinalConnectorSelectionFailed)?,
+
+        _ => Err(errors::RoutingError::DslIncorrectSelectionAlgorithm)
+            .into_report()
+            .attach_printable("Unsupported algorithm received as a result of static routing")?,
+    })
+}
+
+pub async fn refresh_routing_cache_v1(
+    state: &AppState,
+    key: String,
+    algorithm_id: &str,
+    timestamp: i64,
+    #[cfg(feature = "business_profile_routing")] profile_id: Option<String>,
+) -> RoutingResult<()> {
+    #[cfg(feature = "business_profile_routing")]
+    let algorithm = {
+        let algorithm = state
+            .store
+            .find_routing_algorithm_by_profile_id_algorithm_id(
+                &profile_id.unwrap_or_default(),
+                algorithm_id,
+            )
+            .await
+            .change_context(errors::RoutingError::DslMissingInDb)?;
+        let algorithm: routing_types::RoutingAlgorithm = algorithm
+            .algorithm_data
+            .parse_value("RoutingAlgorithm")
+            .change_context(errors::RoutingError::DslParsingError)?;
+        algorithm
+    };
+
+    #[cfg(not(feature = "business_profile_routing"))]
+    let algorithm = {
+        let config = state
+            .store
+            .find_config_by_key(algorithm_id)
+            .await
+            .change_context(errors::RoutingError::DslMissingInDb)
+            .attach_printable("DSL not found in DB")?;
+
+        let algorithm: routing_types::RoutingAlgorithm = config
+            .config
+            .parse_struct("Program")
+            .change_context(errors::RoutingError::DslParsingError)
+            .attach_printable("Error parsing routing algorithm from configs")?;
+        algorithm
+    };
+    let cached_algorithm = match algorithm {
+        routing_types::RoutingAlgorithm::Single(conn) => CachedAlgorithm::Single(conn),
+        routing_types::RoutingAlgorithm::Priority(plist) => CachedAlgorithm::Priority(plist),
+        routing_types::RoutingAlgorithm::VolumeSplit(splits) => {
+            CachedAlgorithm::VolumeSplit(splits)
+        }
+        routing_types::RoutingAlgorithm::Advanced(program) => {
+            let interpreter = backend::VirInterpreterBackend::with_program(program)
+                .into_report()
+                .change_context(errors::RoutingError::DslBackendInitError)
+                .attach_printable("Error initializing DSL interpreter backend")?;
+
+            CachedAlgorithm::Advanced(interpreter)
+        }
+    };
+
+    ROUTING_CACHE
+        .save(key, cached_algorithm, timestamp)
+        .into_report()
+        .change_context(errors::RoutingError::DslCachePoisoned)
+        .attach_printable("Error saving DSL to cache")?;
+
+    Ok(())
+}
+
+pub fn perform_volume_split(
+    mut splits: Vec<routing_types::ConnectorVolumeSplit>,
+    rng_seed: Option<&str>,
+) -> RoutingResult<Vec<routing_types::RoutableConnectorChoice>> {
+    let weights: Vec<u8> = splits.iter().map(|sp| sp.split).collect();
+    let weighted_index = distributions::WeightedIndex::new(weights)
+        .into_report()
+        .change_context(errors::RoutingError::VolumeSplitFailed)
+        .attach_printable("Error creating weighted distribution for volume split")?;
+
+    let idx = if let Some(seed) = rng_seed {
+        let mut hasher = hash_map::DefaultHasher::new();
+        seed.hash(&mut hasher);
+        let hash = hasher.finish();
+
+        let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(hash);
+        weighted_index.sample(&mut rng)
+    } else {
+        let mut rng = rand::thread_rng();
+        weighted_index.sample(&mut rng)
+    };
+
+    splits
+        .get(idx)
+        .ok_or(errors::RoutingError::VolumeSplitFailed)
+        .into_report()
+        .attach_printable("Volume split index lookup failed")?;
+
+    // Panic Safety: We have performed a `get(idx)` operation just above which will
+    // ensure that the index is always present, else throw an error.
+    let removed = splits.remove(idx);
+    splits.insert(0, removed);
+
+    Ok(splits.into_iter().map(|sp| sp.connector).collect())
+}
+
+pub async fn get_merchant_kgraph<'a>(
+    state: &AppState,
+    key_store: &domain::MerchantKeyStore,
+    merchant_last_modified: i64,
+    #[cfg(feature = "business_profile_routing")] profile_id: Option<String>,
+) -> RoutingResult<Arc<euclid_graph::KnowledgeGraph<'a>>> {
+    #[cfg(feature = "business_profile_routing")]
+    let key = {
+        let profile_id = profile_id
+            .clone()
+            .get_required_value("profile_id")
+            .change_context(errors::RoutingError::ProfileIdMissing)?;
+
+        format!("kgraph_{}_{profile_id}", key_store.merchant_id)
+    };
+
+    #[cfg(not(feature = "business_profile_routing"))]
+    let key = format!("kgraph_{}", key_store.merchant_id);
+
+    let kgraph_present = KGRAPH_CACHE
+        .present(&key)
+        .into_report()
+        .change_context(errors::RoutingError::KgraphCacheFailure)
+        .attach_printable("when checking kgraph presence")?;
+
+    let kgraph_expired = KGRAPH_CACHE
+        .expired(&key, merchant_last_modified)
+        .into_report()
+        .change_context(errors::RoutingError::KgraphCacheFailure)
+        .attach_printable("when checking kgraph expiry")?;
+
+    if !kgraph_present || kgraph_expired {
+        refresh_kgraph_cache(
+            state,
+            key_store,
+            merchant_last_modified,
+            key.clone(),
+            #[cfg(feature = "business_profile_routing")]
+            profile_id,
+        )
+        .await?;
+    }
+
+    let cached_kgraph = KGRAPH_CACHE
+        .retrieve(&key)
+        .into_report()
+        .change_context(errors::RoutingError::CacheMiss)
+        .attach_printable("when retrieving kgraph")?;
+
+    Ok(cached_kgraph)
+}
+
+pub async fn refresh_kgraph_cache(
+    state: &AppState,
+    key_store: &domain::MerchantKeyStore,
+    timestamp: i64,
+    key: String,
+    #[cfg(feature = "business_profile_routing")] profile_id: Option<String>,
+) -> RoutingResult<()> {
+    let mut merchant_connector_accounts = state
+        .store
+        .find_merchant_connector_account_by_merchant_id_and_disabled_list(
+            &key_store.merchant_id,
+            false,
+            key_store,
+        )
+        .await
+        .change_context(errors::RoutingError::KgraphCacheRefreshFailed)?;
+
+    merchant_connector_accounts
+        .retain(|mca| mca.connector_type != storage_enums::ConnectorType::PaymentVas);
+
+    #[cfg(feature = "business_profile_routing")]
+    let merchant_connector_accounts = payments_oss::helpers::filter_mca_based_on_business_profile(
+        merchant_connector_accounts,
+        profile_id,
+    );
+
+    let api_mcas: Vec<admin_api::MerchantConnectorResponse> = merchant_connector_accounts
+        .into_iter()
+        .map(|acct| acct.try_into())
+        .collect::<Result<_, _>>()
+        .change_context(errors::RoutingError::KgraphCacheRefreshFailed)?;
+
+    let kgraph = mca_graph::make_mca_graph(api_mcas)
+        .into_report()
+        .change_context(errors::RoutingError::KgraphCacheRefreshFailed)
+        .attach_printable("when construction kgraph")?;
+
+    KGRAPH_CACHE
+        .save(key, kgraph, timestamp)
+        .into_report()
+        .change_context(errors::RoutingError::KgraphCacheRefreshFailed)
+        .attach_printable("when saving kgraph to cache")?;
+
+    Ok(())
+}
+
+async fn perform_kgraph_filtering(
+    state: &AppState,
+    key_store: &domain::MerchantKeyStore,
+    merchant_last_modified: i64,
+    chosen: Vec<routing_types::RoutableConnectorChoice>,
+    backend_input: dsl_inputs::BackendInput,
+    eligible_connectors: Option<&Vec<api_enums::RoutableConnectors>>,
+    #[cfg(feature = "business_profile_routing")] profile_id: Option<String>,
+) -> RoutingResult<Vec<routing_types::RoutableConnectorChoice>> {
+    let context = euclid_graph::AnalysisContext::from_dir_values(
+        backend_input
+            .into_context()
+            .into_report()
+            .change_context(errors::RoutingError::KgraphAnalysisError)?,
+    );
+    let cached_kgraph = get_merchant_kgraph(
+        state,
+        key_store,
+        merchant_last_modified,
+        #[cfg(feature = "business_profile_routing")]
+        profile_id,
+    )
+    .await?;
+
+    let mut final_selection = Vec::<routing_types::RoutableConnectorChoice>::new();
+    for choice in chosen {
+        let routable_connector = choice.connector;
+        let euclid_choice: ast::ConnectorChoice = choice.clone().foreign_into();
+        let dir_val = euclid_choice
+            .into_dir_value()
+            .into_report()
+            .change_context(errors::RoutingError::KgraphAnalysisError)?;
+        let kgraph_eligible = cached_kgraph
+            .check_value_validity(dir_val, &context, &mut Memoization::new())
+            .into_report()
+            .change_context(errors::RoutingError::KgraphAnalysisError)?;
+
+        let filter_eligible =
+            eligible_connectors.map_or(true, |list| list.contains(&routable_connector));
+
+        if kgraph_eligible && filter_eligible {
+            final_selection.push(choice);
+        }
+    }
+
+    Ok(final_selection)
+}
+
+pub async fn perform_eligibility_analysis<F: Clone>(
+    state: &AppState,
+    key_store: &domain::MerchantKeyStore,
+    merchant_last_modified: i64,
+    chosen: Vec<routing_types::RoutableConnectorChoice>,
+    payment_data: &payments_oss::PaymentData<F>,
+    eligible_connectors: Option<&Vec<api_enums::RoutableConnectors>>,
+    #[cfg(feature = "business_profile_routing")] profile_id: Option<String>,
+) -> RoutingResult<Vec<routing_types::RoutableConnectorChoice>> {
+    let backend_input = make_dsl_input(payment_data)?;
+
+    perform_kgraph_filtering(
+        state,
+        key_store,
+        merchant_last_modified,
+        chosen,
+        backend_input,
+        eligible_connectors,
+        #[cfg(feature = "business_profile_routing")]
+        profile_id,
+    )
+    .await
+}
+
+pub async fn perform_fallback_routing<F: Clone>(
+    state: &AppState,
+    key_store: &domain::MerchantKeyStore,
+    merchant_last_modified: i64,
+    payment_data: &payments_oss::PaymentData<F>,
+    eligible_connectors: Option<&Vec<api_enums::RoutableConnectors>>,
+    #[cfg(feature = "business_profile_routing")] profile_id: Option<String>,
+) -> RoutingResult<Vec<routing_types::RoutableConnectorChoice>> {
+    let fallback_config = routing_helpers::get_merchant_default_config(
+        &*state.store,
+        #[cfg(not(feature = "profile_specific_fallback_routing"))]
+        &key_store.merchant_id,
+        #[cfg(feature = "profile_specific_fallback_routing")]
+        {
+            payment_data
+                .payment_intent
+                .profile_id
+                .as_ref()
+                .get_required_value("profile_id")
+                .change_context(errors::RoutingError::ProfileIdMissing)?
+        },
+    )
+    .await
+    .change_context(errors::RoutingError::FallbackConfigFetchFailed)?;
+    let backend_input = make_dsl_input(payment_data)?;
+
+    perform_kgraph_filtering(
+        state,
+        key_store,
+        merchant_last_modified,
+        fallback_config,
+        backend_input,
+        eligible_connectors,
+        #[cfg(feature = "business_profile_routing")]
+        profile_id,
+    )
+    .await
+}
+
+pub async fn perform_eligibility_analysis_with_fallback<F: Clone>(
+    state: &AppState,
+    key_store: &domain::MerchantKeyStore,
+    merchant_last_modified: i64,
+    chosen: Vec<routing_types::RoutableConnectorChoice>,
+    payment_data: &payments_oss::PaymentData<F>,
+    eligible_connectors: Option<Vec<api_enums::RoutableConnectors>>,
+    #[cfg(feature = "business_profile_routing")] profile_id: Option<String>,
+) -> RoutingResult<Vec<routing_types::RoutableConnectorChoice>> {
+    let mut final_selection = perform_eligibility_analysis(
+        state,
+        key_store,
+        merchant_last_modified,
+        chosen,
+        payment_data,
+        eligible_connectors.as_ref(),
+        #[cfg(feature = "business_profile_routing")]
+        profile_id.clone(),
+    )
+    .await?;
+
+    let fallback_selection = perform_fallback_routing(
+        state,
+        key_store,
+        merchant_last_modified,
+        payment_data,
+        eligible_connectors.as_ref(),
+        #[cfg(feature = "business_profile_routing")]
+        profile_id,
+    )
+    .await;
+
+    final_selection.append(
+        &mut fallback_selection
+            .unwrap_or_default()
+            .iter()
+            .filter(|&routable_connector_choice| {
+                !final_selection.contains(routable_connector_choice)
+            })
+            .cloned()
+            .collect::<Vec<_>>(),
+    );
+
+    let final_selected_connectors = final_selection
+        .iter()
+        .map(|item| item.connector)
+        .collect::<Vec<_>>();
+    logger::debug!(final_selected_connectors_for_routing=?final_selected_connectors, "List of final selected connectors for routing");
+
+    Ok(final_selection)
+}
+
+pub async fn perform_session_flow_routing(
+    session_input: SessionFlowRoutingInput<'_>,
+) -> RoutingResult<FxHashMap<api_enums::PaymentMethodType, routing_types::SessionRoutingChoice>> {
+    let mut pm_type_map: FxHashMap<api_enums::PaymentMethodType, FxHashMap<String, api::GetToken>> =
+        FxHashMap::default();
+    let merchant_last_modified = session_input
+        .merchant_account
+        .modified_at
+        .assume_utc()
+        .unix_timestamp();
+
+    #[cfg(feature = "business_profile_routing")]
+    let routing_algorithm: MerchantAccountRoutingAlgorithm = {
+        let profile_id = session_input
+            .payment_intent
+            .profile_id
+            .clone()
+            .get_required_value("profile_id")
+            .change_context(errors::RoutingError::ProfileIdMissing)?;
+
+        let business_profile = session_input
+            .state
+            .store
+            .find_business_profile_by_profile_id(&profile_id)
+            .await
+            .change_context(errors::RoutingError::ProfileNotFound)?;
+
+        business_profile
+            .routing_algorithm
+            .clone()
+            .map(|val| val.parse_value("MerchantAccountRoutingAlgorithm"))
+            .transpose()
+            .change_context(errors::RoutingError::InvalidRoutingAlgorithmStructure)?
+            .unwrap_or_default()
+    };
+
+    #[cfg(not(feature = "business_profile_routing"))]
+    let routing_algorithm: MerchantAccountRoutingAlgorithm = {
+        session_input
+            .merchant_account
+            .routing_algorithm
+            .clone()
+            .map(|val| val.parse_value("MerchantAccountRoutingAlgorithm"))
+            .transpose()
+            .change_context(errors::RoutingError::InvalidRoutingAlgorithmStructure)?
+            .unwrap_or_default()
+    };
+
+    let payment_method_input = dsl_inputs::PaymentMethodInput {
+        payment_method: None,
+        payment_method_type: None,
+        card_network: None,
+    };
+
+    let payment_input = dsl_inputs::PaymentInput {
+        amount: session_input.payment_intent.amount,
+        currency: session_input
+            .payment_intent
+            .currency
+            .get_required_value("Currency")
+            .change_context(errors::RoutingError::DslMissingRequiredField {
+                field_name: "currency".to_string(),
+            })?,
+        authentication_type: session_input.payment_attempt.authentication_type,
+        card_bin: None,
+        capture_method: session_input
+            .payment_attempt
+            .capture_method
+            .and_then(|cm| cm.foreign_into()),
+        business_country: session_input
+            .payment_intent
+            .business_country
+            .map(api_enums::Country::from_alpha2),
+        billing_country: session_input
+            .country
+            .map(storage_enums::Country::from_alpha2),
+        business_label: session_input.payment_intent.business_label.clone(),
+        setup_future_usage: session_input.payment_intent.setup_future_usage,
+    };
+
+    let metadata = session_input
+        .payment_intent
+        .metadata
+        .clone()
+        .map(|val| val.parse_value("routing_parameters"))
+        .transpose()
+        .change_context(errors::RoutingError::MetadataParsingError)
+        .attach_printable("Unable to parse routing_parameters from metadata of payment_intent")
+        .unwrap_or_else(|err| {
+            logger::error!(?err);
+            None
+        });
+
+    let mut backend_input = dsl_inputs::BackendInput {
+        metadata,
+        payment: payment_input,
+        payment_method: payment_method_input,
+        mandate: dsl_inputs::MandateData {
+            mandate_acceptance_type: None,
+            mandate_type: None,
+            payment_type: None,
+        },
+    };
+
+    for connector_data in session_input.chosen.iter() {
+        pm_type_map
+            .entry(connector_data.payment_method_type)
+            .or_default()
+            .insert(
+                connector_data.connector.connector_name.to_string(),
+                connector_data.connector.get_token.clone(),
+            );
+    }
+
+    let mut result: FxHashMap<api_enums::PaymentMethodType, routing_types::SessionRoutingChoice> =
+        FxHashMap::default();
+
+    for (pm_type, allowed_connectors) in pm_type_map {
+        let euclid_pmt: euclid_enums::PaymentMethodType = pm_type;
+        let euclid_pm: euclid_enums::PaymentMethod = euclid_pmt.into();
+
+        backend_input.payment_method.payment_method = Some(euclid_pm);
+        backend_input.payment_method.payment_method_type = Some(euclid_pmt);
+
+        let session_pm_input = SessionRoutingPmTypeInput {
+            state: session_input.state,
+            key_store: session_input.key_store,
+            merchant_last_modified,
+            attempt_id: &session_input.payment_attempt.attempt_id,
+            routing_algorithm: &routing_algorithm,
+            backend_input: backend_input.clone(),
+            allowed_connectors,
+            #[cfg(any(
+                feature = "business_profile_routing",
+                feature = "profile_specific_fallback_routing"
+            ))]
+            profile_id: session_input.payment_intent.profile_id.clone(),
+        };
+        let maybe_choice = perform_session_routing_for_pm_type(session_pm_input).await?;
+
+        // (connector, sub_label)
+        if let Some(data) = maybe_choice {
+            result.insert(
+                pm_type,
+                routing_types::SessionRoutingChoice {
+                    connector: data.0,
+                    #[cfg(not(feature = "connector_choice_mca_id"))]
+                    sub_label: data.1,
+                    payment_method_type: pm_type,
+                },
+            );
+        }
+    }
+
+    Ok(result)
+}
+
+async fn perform_session_routing_for_pm_type(
+    session_pm_input: SessionRoutingPmTypeInput<'_>,
+) -> RoutingResult<Option<(api::ConnectorData, Option<String>)>> {
+    let merchant_id = &session_pm_input.key_store.merchant_id;
+
+    let chosen_connectors = match session_pm_input.routing_algorithm {
+        MerchantAccountRoutingAlgorithm::V1(algorithm_ref) => {
+            if let Some(ref algorithm_id) = algorithm_ref.algorithm_id {
+                let key = ensure_algorithm_cached_v1(
+                    &session_pm_input.state.clone(),
+                    merchant_id,
+                    algorithm_ref.timestamp,
+                    algorithm_id,
+                    #[cfg(feature = "business_profile_routing")]
+                    session_pm_input.profile_id.clone(),
+                )
+                .await?;
+
+                let cached_algorithm = ROUTING_CACHE
+                    .retrieve(&key)
+                    .into_report()
+                    .change_context(errors::RoutingError::CacheMiss)
+                    .attach_printable("unable to retrieve cached routing algorithm")?;
+
+                match cached_algorithm.as_ref() {
+                    CachedAlgorithm::Single(conn) => vec![(**conn).clone()],
+                    CachedAlgorithm::Priority(plist) => plist.clone(),
+                    CachedAlgorithm::VolumeSplit(splits) => {
+                        perform_volume_split(splits.to_vec(), Some(session_pm_input.attempt_id))
+                            .change_context(errors::RoutingError::ConnectorSelectionFailed)?
+                    }
+                    CachedAlgorithm::Advanced(interpreter) => execute_dsl_and_get_connector_v1(
+                        session_pm_input.backend_input.clone(),
+                        interpreter,
+                    )?,
+                }
+            } else {
+                routing_helpers::get_merchant_default_config(
+                    &*session_pm_input.state.clone().store,
+                    #[cfg(not(feature = "profile_specific_fallback_routing"))]
+                    merchant_id,
+                    #[cfg(feature = "profile_specific_fallback_routing")]
+                    {
+                        session_pm_input
+                            .profile_id
+                            .as_ref()
+                            .get_required_value("profile_id")
+                            .change_context(errors::RoutingError::ProfileIdMissing)?
+                    },
+                )
+                .await
+                .change_context(errors::RoutingError::FallbackConfigFetchFailed)?
+            }
+        }
+    };
+
+    let mut final_selection = perform_kgraph_filtering(
+        &session_pm_input.state.clone(),
+        session_pm_input.key_store,
+        session_pm_input.merchant_last_modified,
+        chosen_connectors,
+        session_pm_input.backend_input.clone(),
+        None,
+        #[cfg(feature = "business_profile_routing")]
+        session_pm_input.profile_id.clone(),
+    )
+    .await?;
+
+    if final_selection.is_empty() {
+        let fallback = routing_helpers::get_merchant_default_config(
+            &*session_pm_input.state.clone().store,
+            #[cfg(not(feature = "profile_specific_fallback_routing"))]
+            merchant_id,
+            #[cfg(feature = "profile_specific_fallback_routing")]
+            {
+                session_pm_input
+                    .profile_id
+                    .as_ref()
+                    .get_required_value("profile_id")
+                    .change_context(errors::RoutingError::ProfileIdMissing)?
+            },
+        )
+        .await
+        .change_context(errors::RoutingError::FallbackConfigFetchFailed)?;
+
+        final_selection = perform_kgraph_filtering(
+            &session_pm_input.state.clone(),
+            session_pm_input.key_store,
+            session_pm_input.merchant_last_modified,
+            fallback,
+            session_pm_input.backend_input,
+            None,
+            #[cfg(feature = "business_profile_routing")]
+            session_pm_input.profile_id.clone(),
+        )
+        .await?;
+    }
+
+    let mut final_choice: Option<(api::ConnectorData, Option<String>)> = None;
+
+    for selection in final_selection {
+        let connector_name = selection.connector.to_string();
+        if let Some(get_token) = session_pm_input.allowed_connectors.get(&connector_name) {
+            let connector_data = api::ConnectorData::get_connector_by_name(
+                &session_pm_input.state.clone().conf.connectors,
+                &connector_name,
+                get_token.clone(),
+                #[cfg(feature = "connector_choice_mca_id")]
+                selection.merchant_connector_id,
+                #[cfg(not(feature = "connector_choice_mca_id"))]
+                None,
+            )
+            .change_context(errors::RoutingError::InvalidConnectorName(connector_name))?;
+            #[cfg(not(feature = "connector_choice_mca_id"))]
+            let sub_label = selection.sub_label;
+            #[cfg(feature = "connector_choice_mca_id")]
+            let sub_label = None;
+
+            final_choice = Some((connector_data, sub_label));
+            break;
+        }
+    }
+
+    Ok(final_choice)
+}
diff --git a/crates/router/src/core/payments/routing/transformers.rs b/crates/router/src/core/payments/routing/transformers.rs
new file mode 100644
index 000000000000..de94a36248ff
--- /dev/null
+++ b/crates/router/src/core/payments/routing/transformers.rs
@@ -0,0 +1,121 @@
+use api_models::{self, enums as api_enums, routing as routing_types};
+use diesel_models::enums as storage_enums;
+use euclid::{enums as dsl_enums, frontend::ast as dsl_ast};
+
+use crate::types::transformers::{ForeignFrom, ForeignInto};
+
+impl ForeignFrom<routing_types::RoutableConnectorChoice> for dsl_ast::ConnectorChoice {
+    fn foreign_from(from: routing_types::RoutableConnectorChoice) -> Self {
+        Self {
+            // #[cfg(feature = "backwards_compatibility")]
+            // choice_kind: from.choice_kind.foreign_into(),
+            connector: from.connector.foreign_into(),
+            #[cfg(not(feature = "connector_choice_mca_id"))]
+            sub_label: from.sub_label,
+        }
+    }
+}
+
+impl ForeignFrom<storage_enums::CaptureMethod> for Option<dsl_enums::CaptureMethod> {
+    fn foreign_from(value: storage_enums::CaptureMethod) -> Self {
+        match value {
+            storage_enums::CaptureMethod::Automatic => Some(dsl_enums::CaptureMethod::Automatic),
+            storage_enums::CaptureMethod::Manual => Some(dsl_enums::CaptureMethod::Manual),
+            _ => None,
+        }
+    }
+}
+
+impl ForeignFrom<api_models::payments::AcceptanceType> for dsl_enums::MandateAcceptanceType {
+    fn foreign_from(from: api_models::payments::AcceptanceType) -> Self {
+        match from {
+            api_models::payments::AcceptanceType::Online => Self::Online,
+            api_models::payments::AcceptanceType::Offline => Self::Offline,
+        }
+    }
+}
+
+impl ForeignFrom<api_models::payments::MandateType> for dsl_enums::MandateType {
+    fn foreign_from(from: api_models::payments::MandateType) -> Self {
+        match from {
+            api_models::payments::MandateType::MultiUse(_) => Self::MultiUse,
+            api_models::payments::MandateType::SingleUse(_) => Self::SingleUse,
+        }
+    }
+}
+
+impl ForeignFrom<storage_enums::MandateDataType> for dsl_enums::MandateType {
+    fn foreign_from(from: storage_enums::MandateDataType) -> Self {
+        match from {
+            storage_enums::MandateDataType::MultiUse(_) => Self::MultiUse,
+            storage_enums::MandateDataType::SingleUse(_) => Self::SingleUse,
+        }
+    }
+}
+
+impl ForeignFrom<api_enums::RoutableConnectors> for dsl_enums::Connector {
+    fn foreign_from(from: api_enums::RoutableConnectors) -> Self {
+        match from {
+            #[cfg(feature = "dummy_connector")]
+            api_enums::RoutableConnectors::DummyConnector1 => Self::DummyConnector1,
+            #[cfg(feature = "dummy_connector")]
+            api_enums::RoutableConnectors::DummyConnector2 => Self::DummyConnector2,
+            #[cfg(feature = "dummy_connector")]
+            api_enums::RoutableConnectors::DummyConnector3 => Self::DummyConnector3,
+            #[cfg(feature = "dummy_connector")]
+            api_enums::RoutableConnectors::DummyConnector4 => Self::DummyConnector4,
+            #[cfg(feature = "dummy_connector")]
+            api_enums::RoutableConnectors::DummyConnector5 => Self::DummyConnector5,
+            #[cfg(feature = "dummy_connector")]
+            api_enums::RoutableConnectors::DummyConnector6 => Self::DummyConnector6,
+            #[cfg(feature = "dummy_connector")]
+            api_enums::RoutableConnectors::DummyConnector7 => Self::DummyConnector7,
+            api_enums::RoutableConnectors::Aci => Self::Aci,
+            api_enums::RoutableConnectors::Adyen => Self::Adyen,
+            api_enums::RoutableConnectors::Airwallex => Self::Airwallex,
+            api_enums::RoutableConnectors::Authorizedotnet => Self::Authorizedotnet,
+            api_enums::RoutableConnectors::Bitpay => Self::Bitpay,
+            api_enums::RoutableConnectors::Bambora => Self::Bambora,
+            api_enums::RoutableConnectors::Bluesnap => Self::Bluesnap,
+            api_enums::RoutableConnectors::Boku => Self::Boku,
+            api_enums::RoutableConnectors::Braintree => Self::Braintree,
+            api_enums::RoutableConnectors::Cashtocode => Self::Cashtocode,
+            api_enums::RoutableConnectors::Checkout => Self::Checkout,
+            api_enums::RoutableConnectors::Coinbase => Self::Coinbase,
+            api_enums::RoutableConnectors::Cryptopay => Self::Cryptopay,
+            api_enums::RoutableConnectors::Cybersource => Self::Cybersource,
+            api_enums::RoutableConnectors::Dlocal => Self::Dlocal,
+            api_enums::RoutableConnectors::Fiserv => Self::Fiserv,
+            api_enums::RoutableConnectors::Forte => Self::Forte,
+            api_enums::RoutableConnectors::Globalpay => Self::Globalpay,
+            api_enums::RoutableConnectors::Globepay => Self::Globepay,
+            api_enums::RoutableConnectors::Gocardless => Self::Gocardless,
+            api_enums::RoutableConnectors::Helcim => Self::Helcim,
+            api_enums::RoutableConnectors::Iatapay => Self::Iatapay,
+            api_enums::RoutableConnectors::Klarna => Self::Klarna,
+            api_enums::RoutableConnectors::Mollie => Self::Mollie,
+            api_enums::RoutableConnectors::Multisafepay => Self::Multisafepay,
+            api_enums::RoutableConnectors::Nexinets => Self::Nexinets,
+            api_enums::RoutableConnectors::Nmi => Self::Nmi,
+            api_enums::RoutableConnectors::Noon => Self::Noon,
+            api_enums::RoutableConnectors::Nuvei => Self::Nuvei,
+            api_enums::RoutableConnectors::Opennode => Self::Opennode,
+            api_enums::RoutableConnectors::Payme => Self::Payme,
+            api_enums::RoutableConnectors::Paypal => Self::Paypal,
+            api_enums::RoutableConnectors::Payu => Self::Payu,
+            api_enums::RoutableConnectors::Powertranz => Self::Powertranz,
+            api_enums::RoutableConnectors::Rapyd => Self::Rapyd,
+            api_enums::RoutableConnectors::Shift4 => Self::Shift4,
+            api_enums::RoutableConnectors::Square => Self::Square,
+            api_enums::RoutableConnectors::Stax => Self::Stax,
+            api_enums::RoutableConnectors::Stripe => Self::Stripe,
+            api_enums::RoutableConnectors::Trustpay => Self::Trustpay,
+            api_enums::RoutableConnectors::Tsys => Self::Tsys,
+            api_enums::RoutableConnectors::Volt => Self::Volt,
+            api_enums::RoutableConnectors::Wise => Self::Wise,
+            api_enums::RoutableConnectors::Worldline => Self::Worldline,
+            api_enums::RoutableConnectors::Worldpay => Self::Worldpay,
+            api_enums::RoutableConnectors::Zen => Self::Zen,
+        }
+    }
+}
diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs
index d2ced5af3466..6c6b4ae9339f 100644
--- a/crates/router/src/core/payments/transformers.rs
+++ b/crates/router/src/core/payments/transformers.rs
@@ -346,7 +346,7 @@ pub fn payments_to_payments_response<R, Op, F: Clone>(
     connector_request_reference_id_config: &ConnectorRequestReferenceIdConfig,
     connector_http_status_code: Option<u16>,
     external_latency: Option<u128>,
-    is_latency_header_enabled: Option<bool>,
+    _is_latency_header_enabled: Option<bool>,
 ) -> RouterResponse<api::PaymentsResponse>
 where
     Op: Debug,
@@ -451,23 +451,17 @@ where
             payment_confirm_source.to_string(),
         ))
     }
-    if Some(true) == is_latency_header_enabled {
-        headers.extend(
-            external_latency
-                .map(|latency| vec![(X_HS_LATENCY.to_string(), latency.to_string())])
-                .unwrap_or_default(),
-        );
-    }
+
+    headers.extend(
+        external_latency
+            .map(|latency| vec![(X_HS_LATENCY.to_string(), latency.to_string())])
+            .unwrap_or_default(),
+    );
+
     let output = Ok(match payment_request {
         Some(_request) => {
-            if payments::is_start_pay(&operation)
-                && payment_data
-                    .connector_response
-                    .authentication_data
-                    .is_some()
-            {
-                let redirection_data = payment_data
-                    .connector_response
+            if payments::is_start_pay(&operation) && payment_attempt.authentication_data.is_some() {
+                let redirection_data = payment_attempt
                     .authentication_data
                     .get_required_value("redirection_data")?;
 
@@ -523,16 +517,15 @@ where
                                 display_to_timestamp: wait_screen_data.display_to_timestamp,
                             }
                         }))
-                        .or(payment_data
-                            .connector_response
-                            .authentication_data
-                            .map(|_| api_models::payments::NextActionData::RedirectToUrl {
+                        .or(payment_attempt.authentication_data.as_ref().map(|_| {
+                            api_models::payments::NextActionData::RedirectToUrl {
                                 redirect_to_url: helpers::create_startpay_url(
                                     server,
                                     &payment_attempt,
                                     &payment_intent,
                                 ),
-                            }));
+                            }
+                        }));
                 };
 
                 // next action check for third party sdk session (for ex: Apple pay through trustpay has third party sdk session response)
@@ -691,6 +684,7 @@ where
                         .set_payment_link(payment_link_data)
                         .set_profile_id(payment_intent.profile_id)
                         .set_attempt_count(payment_intent.attempt_count)
+                        .set_merchant_connector_id(payment_attempt.merchant_connector_id)
                         .to_owned(),
                     headers,
                 ))
@@ -1055,7 +1049,7 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsSyncData
                 }
                 None => types::ResponseId::NoResponseId,
             },
-            encoded_data: payment_data.connector_response.encoded_data,
+            encoded_data: payment_data.payment_attempt.encoded_data,
             capture_method: payment_data.payment_attempt.capture_method,
             connector_meta: payment_data.payment_attempt.connector_metadata,
             sync_type: match payment_data.multiple_capture_data {
@@ -1102,6 +1096,7 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsCaptureD
             &additional_data.state.conf.connectors,
             &additional_data.connector_name,
             api::GetToken::Connector,
+            payment_data.payment_attempt.merchant_connector_id.clone(),
         )?;
         let amount_to_capture: i64 = payment_data
             .payment_attempt
@@ -1150,6 +1145,7 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsCancelDa
             &additional_data.state.conf.connectors,
             &additional_data.connector_name,
             api::GetToken::Connector,
+            payment_data.payment_attempt.merchant_connector_id.clone(),
         )?;
         let browser_info: Option<types::BrowserInformation> = payment_data
             .payment_attempt
@@ -1353,7 +1349,7 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::CompleteAuthoriz
             browser_info,
             email: payment_data.email,
             payment_method_data: payment_data.payment_method_data,
-            connector_transaction_id: payment_data.connector_response.connector_transaction_id,
+            connector_transaction_id: payment_data.payment_attempt.connector_transaction_id,
             redirect_response,
             connector_meta: payment_data.payment_attempt.connector_metadata,
         })
diff --git a/crates/router/src/core/payouts.rs b/crates/router/src/core/payouts.rs
index ddb2a017e35a..f1136a35a65a 100644
--- a/crates/router/src/core/payouts.rs
+++ b/crates/router/src/core/payouts.rs
@@ -112,7 +112,7 @@ where
 
     // Validate create request
     let (payout_id, payout_method_data) =
-        validator::validate_create_request(&state, &merchant_account, &req).await?;
+        validator::validate_create_request(&state, &merchant_account, &req, &key_store).await?;
 
     // Create DB entries
     let mut payout_data = payout_create_db_entries(
@@ -403,6 +403,7 @@ pub async fn payouts_fulfill_core(
             &payout_attempt.merchant_id,
             &payout_attempt.payout_id,
             Some(&payout_data.payouts.payout_type),
+            &key_store,
         )
         .await?
         .get_required_value("payout_method_data")?,
@@ -458,6 +459,7 @@ pub async fn call_connector_payout(
                 &payout_attempt.merchant_id,
                 &payout_attempt.payout_id,
                 Some(&payouts.payout_type),
+                key_store,
             )
             .await?
             .get_required_value("payout_method_data")?,
diff --git a/crates/router/src/core/payouts/helpers.rs b/crates/router/src/core/payouts/helpers.rs
index 9890cd9d5efd..39079ea36cd6 100644
--- a/crates/router/src/core/payouts/helpers.rs
+++ b/crates/router/src/core/payouts/helpers.rs
@@ -28,6 +28,7 @@ use crate::{
     utils::{self, OptionExt},
 };
 
+#[allow(clippy::too_many_arguments)]
 pub async fn make_payout_method_data<'a>(
     state: &'a AppState,
     payout_method_data: Option<&api::PayoutMethodData>,
@@ -36,6 +37,7 @@ pub async fn make_payout_method_data<'a>(
     merchant_id: &str,
     payout_id: &str,
     payout_type: Option<&api_enums::PayoutType>,
+    merchant_key_store: &domain::MerchantKeyStore,
 ) -> RouterResult<Option<api::PayoutMethodData>> {
     let db = &*state.store;
     let hyperswitch_token = if let Some(payout_token) = payout_token {
@@ -67,14 +69,16 @@ pub async fn make_payout_method_data<'a>(
     match (payout_method_data.to_owned(), hyperswitch_token) {
         // Get operation
         (None, Some(payout_token)) => {
-            let (pm, supplementary_data) = vault::Vault::get_payout_method_data_from_temporary_locker(
-                state,
-                &payout_token,
-            )
-            .await
-            .attach_printable(
-                "Payout method for given token not found or there was a problem fetching it",
-            )?;
+            let (pm, supplementary_data) =
+                vault::Vault::get_payout_method_data_from_temporary_locker(
+                    state,
+                    &payout_token,
+                    merchant_key_store,
+                )
+                .await
+                .attach_printable(
+                    "Payout method for given token not found or there was a problem fetching it",
+                )?;
             utils::when(
                 supplementary_data
                     .customer_id
@@ -93,6 +97,7 @@ pub async fn make_payout_method_data<'a>(
                 payout_token.to_owned(),
                 payout_method,
                 Some(customer_id.to_owned()),
+                merchant_key_store,
             )
             .await?;
 
diff --git a/crates/router/src/core/payouts/validator.rs b/crates/router/src/core/payouts/validator.rs
index c815d91e41dd..3793ee523dc3 100644
--- a/crates/router/src/core/payouts/validator.rs
+++ b/crates/router/src/core/payouts/validator.rs
@@ -57,6 +57,7 @@ pub async fn validate_create_request(
     state: &AppState,
     merchant_account: &domain::MerchantAccount,
     req: &payouts::PayoutCreateRequest,
+    merchant_key_store: &domain::MerchantKeyStore,
 ) -> RouterResult<(String, Option<payouts::PayoutMethodData>)> {
     let merchant_id = &merchant_account.merchant_id;
 
@@ -103,6 +104,7 @@ pub async fn validate_create_request(
                 &merchant_account.merchant_id,
                 payout_id.as_ref(),
                 req.payout_type.as_ref(),
+                merchant_key_store,
             )
             .await?
         }
diff --git a/crates/router/src/core/refunds.rs b/crates/router/src/core/refunds.rs
index 44e2b84dbd75..a42e46ca62d5 100644
--- a/crates/router/src/core/refunds.rs
+++ b/crates/router/src/core/refunds.rs
@@ -146,6 +146,7 @@ pub async fn trigger_refund_to_gateway(
         &state.conf.connectors,
         &routed_through,
         api::GetToken::Connector,
+        payment_attempt.merchant_connector_id.clone(),
     )?;
 
     let currency = payment_attempt.currency.ok_or_else(|| {
@@ -380,6 +381,7 @@ pub async fn sync_refund_with_gateway(
         &state.conf.connectors,
         &connector_id,
         api::GetToken::Connector,
+        payment_attempt.connector.clone(),
     )
     .change_context(errors::ApiErrorResponse::InternalServerError)
     .attach_printable("Failed to get the connector")?;
@@ -474,14 +476,13 @@ pub async fn sync_refund_with_gateway(
 pub async fn refund_update_core(
     state: AppState,
     merchant_account: domain::MerchantAccount,
-    refund_id: &str,
     req: refunds::RefundUpdateRequest,
 ) -> RouterResponse<refunds::RefundResponse> {
     let db = state.store.as_ref();
     let refund = db
         .find_refund_by_merchant_id_refund_id(
             &merchant_account.merchant_id,
-            refund_id,
+            &req.refund_id,
             merchant_account.storage_scheme,
         )
         .await
@@ -499,7 +500,9 @@ pub async fn refund_update_core(
         )
         .await
         .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable_lazy(|| format!("Unable to update refund with refund_id: {refund_id}"))?;
+        .attach_printable_lazy(|| {
+            format!("Unable to update refund with refund_id: {}", req.refund_id)
+        })?;
 
     Ok(services::ApplicationResponse::Json(response.foreign_into()))
 }
@@ -519,14 +522,13 @@ pub async fn validate_and_create_refund(
     creds_identifier: Option<String>,
 ) -> RouterResult<refunds::RefundResponse> {
     let db = &*state.store;
-    let (refund_id, all_refunds, currency, refund_create_req, refund);
 
     // Only for initial dev and testing
     let refund_type = req.refund_type.unwrap_or_default();
 
     // If Refund Id not passed in request Generate one.
 
-    refund_id = core_utils::get_or_generate_id("refund_id", &req.refund_id, "ref")?;
+    let refund_id = core_utils::get_or_generate_id("refund_id", &req.refund_id, "ref")?;
 
     let predicate = req
         .merchant_id
@@ -546,7 +548,7 @@ pub async fn validate_and_create_refund(
         .attach_printable("Transaction in invalid. Missing field \"connector_transaction_id\" in payment_attempt.")
     })?;
 
-    all_refunds = db
+    let all_refunds = db
         .find_refund_by_merchant_id_connector_transaction_id(
             &merchant_account.merchant_id,
             &connecter_transaction_id,
@@ -555,7 +557,7 @@ pub async fn validate_and_create_refund(
         .await
         .to_not_found_response(errors::ApiErrorResponse::RefundNotFound)?;
 
-    currency = payment_attempt.currency.get_required_value("currency")?;
+    let currency = payment_attempt.currency.get_required_value("currency")?;
 
     //[#249]: Add Connector Based Validation here.
     validator::validate_payment_order_age(&payment_intent.created_at, state.conf.refund.max_age)
@@ -583,10 +585,10 @@ pub async fn validate_and_create_refund(
         .into_report()
         .attach_printable("No connector populated in payment attempt")?;
 
-    refund_create_req = storage::RefundNew::default()
+    let refund_create_req = storage::RefundNew::default()
         .set_refund_id(refund_id.to_string())
         .set_internal_reference_id(utils::generate_id(consts::ID_LENGTH, "refid"))
-        .set_external_reference_id(Some(refund_id))
+        .set_external_reference_id(Some(refund_id.clone()))
         .set_payment_id(req.payment_id)
         .set_merchant_id(merchant_account.merchant_id.clone())
         .set_connector_transaction_id(connecter_transaction_id.to_string())
@@ -602,24 +604,42 @@ pub async fn validate_and_create_refund(
         .set_description(req.reason.clone())
         .set_attempt_id(payment_attempt.attempt_id.clone())
         .set_refund_reason(req.reason)
+        .set_profile_id(payment_intent.profile_id.clone())
         .to_owned();
 
-    refund = db
+    let refund = match db
         .insert_refund(refund_create_req, merchant_account.storage_scheme)
         .await
-        .to_duplicate_response(errors::ApiErrorResponse::DuplicateRefundRequest)?;
-
-    schedule_refund_execution(
-        state,
-        refund.clone(),
-        refund_type,
-        merchant_account,
-        key_store,
-        payment_attempt,
-        payment_intent,
-        creds_identifier,
-    )
-    .await?;
+    {
+        Ok(refund) => {
+            schedule_refund_execution(
+                state,
+                refund.clone(),
+                refund_type,
+                merchant_account,
+                key_store,
+                payment_attempt,
+                payment_intent,
+                creds_identifier,
+            )
+            .await?
+        }
+        Err(err) => {
+            if err.current_context().is_db_unique_violation() {
+                db.find_refund_by_merchant_id_refund_id(
+                    merchant_account.merchant_id.as_str(),
+                    refund_id.as_str(),
+                    merchant_account.storage_scheme,
+                )
+                .await
+                .to_not_found_response(errors::ApiErrorResponse::RefundNotFound)?
+            } else {
+                return Err(err)
+                    .change_context(errors::ApiErrorResponse::RefundNotFound)
+                    .attach_printable("Inserting Refund failed");
+            }
+        }
+    };
 
     Ok(refund.foreign_into())
 }
@@ -679,7 +699,7 @@ pub async fn refund_list(
 pub async fn refund_filter_list(
     state: AppState,
     merchant_account: domain::MerchantAccount,
-    req: api_models::refunds::TimeRange,
+    req: api_models::payments::TimeRange,
 ) -> RouterResponse<api_models::refunds::RefundListMetaData> {
     let db = state.store;
     let filter_list = db
@@ -704,6 +724,7 @@ impl ForeignFrom<storage::Refund> for api::RefundResponse {
             currency: refund.currency.to_string(),
             reason: refund.refund_reason,
             status: refund.refund_status.foreign_into(),
+            profile_id: refund.profile_id,
             metadata: refund.metadata,
             error_message: refund.refund_error_message,
             error_code: refund.refund_error_code,
diff --git a/crates/router/src/core/routing.rs b/crates/router/src/core/routing.rs
new file mode 100644
index 000000000000..4171c3385637
--- /dev/null
+++ b/crates/router/src/core/routing.rs
@@ -0,0 +1,838 @@
+pub mod helpers;
+pub mod transformers;
+
+use api_models::routing::{self as routing_types, RoutingAlgorithmId};
+#[cfg(feature = "business_profile_routing")]
+use api_models::routing::{RoutingRetrieveLinkQuery, RoutingRetrieveQuery};
+#[cfg(not(feature = "business_profile_routing"))]
+use common_utils::ext_traits::{Encode, StringExt};
+#[cfg(not(feature = "business_profile_routing"))]
+use diesel_models::configs;
+#[cfg(feature = "business_profile_routing")]
+use diesel_models::routing_algorithm::RoutingAlgorithm;
+use error_stack::{IntoReport, ResultExt};
+use rustc_hash::FxHashSet;
+
+#[cfg(feature = "business_profile_routing")]
+use crate::types::transformers::{ForeignInto, ForeignTryInto};
+use crate::{
+    consts,
+    core::{
+        errors::{RouterResponse, StorageErrorExt},
+        utils as core_utils,
+    },
+    routes::AppState,
+    types::domain,
+    utils::{self, OptionExt, ValueExt},
+};
+#[cfg(not(feature = "business_profile_routing"))]
+use crate::{core::errors, services::api as service_api, types::storage};
+#[cfg(feature = "business_profile_routing")]
+use crate::{errors, services::api as service_api};
+
+pub async fn retrieve_merchant_routing_dictionary(
+    state: AppState,
+    merchant_account: domain::MerchantAccount,
+    #[cfg(feature = "business_profile_routing")] query_params: RoutingRetrieveQuery,
+) -> RouterResponse<routing_types::RoutingKind> {
+    #[cfg(feature = "business_profile_routing")]
+    {
+        let routing_metadata = state
+            .store
+            .list_routing_algorithm_metadata_by_merchant_id(
+                &merchant_account.merchant_id,
+                i64::from(query_params.limit.unwrap_or_default()),
+                i64::from(query_params.offset.unwrap_or_default()),
+            )
+            .await
+            .to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)?;
+        let result = routing_metadata
+            .into_iter()
+            .map(ForeignInto::foreign_into)
+            .collect::<Vec<_>>();
+
+        Ok(service_api::ApplicationResponse::Json(
+            routing_types::RoutingKind::RoutingAlgorithm(result),
+        ))
+    }
+    #[cfg(not(feature = "business_profile_routing"))]
+    Ok(service_api::ApplicationResponse::Json(
+        routing_types::RoutingKind::Config(
+            helpers::get_merchant_routing_dictionary(
+                state.store.as_ref(),
+                &merchant_account.merchant_id,
+            )
+            .await?,
+        ),
+    ))
+}
+
+pub async fn create_routing_config(
+    state: AppState,
+    merchant_account: domain::MerchantAccount,
+    key_store: domain::MerchantKeyStore,
+    request: routing_types::RoutingConfigRequest,
+) -> RouterResponse<routing_types::RoutingDictionaryRecord> {
+    let db = state.store.as_ref();
+
+    let name = request
+        .name
+        .get_required_value("name")
+        .change_context(errors::ApiErrorResponse::MissingRequiredField { field_name: "name" })
+        .attach_printable("Name of config not given")?;
+
+    let description = request
+        .description
+        .get_required_value("description")
+        .change_context(errors::ApiErrorResponse::MissingRequiredField {
+            field_name: "description",
+        })
+        .attach_printable("Description of config not given")?;
+
+    let algorithm = request
+        .algorithm
+        .get_required_value("algorithm")
+        .change_context(errors::ApiErrorResponse::MissingRequiredField {
+            field_name: "algorithm",
+        })
+        .attach_printable("Algorithm of config not given")?;
+
+    let algorithm_id = common_utils::generate_id(
+        consts::ROUTING_CONFIG_ID_LENGTH,
+        &format!("routing_{}", &merchant_account.merchant_id),
+    );
+
+    #[cfg(feature = "business_profile_routing")]
+    {
+        let profile_id = request
+            .profile_id
+            .get_required_value("profile_id")
+            .change_context(errors::ApiErrorResponse::MissingRequiredField {
+                field_name: "profile_id",
+            })
+            .attach_printable("Profile_id not provided")?;
+
+        core_utils::validate_and_get_business_profile(
+            db,
+            Some(&profile_id),
+            &merchant_account.merchant_id,
+        )
+        .await?;
+
+        helpers::validate_connectors_in_routing_config(
+            db,
+            &key_store,
+            &merchant_account.merchant_id,
+            &profile_id,
+            &algorithm,
+        )
+        .await?;
+
+        let timestamp = common_utils::date_time::now();
+        let algo = RoutingAlgorithm {
+            algorithm_id: algorithm_id.clone(),
+            profile_id,
+            merchant_id: merchant_account.merchant_id,
+            name: name.clone(),
+            description: Some(description.clone()),
+            kind: algorithm.get_kind().foreign_into(),
+            algorithm_data: serde_json::json!(algorithm),
+            created_at: timestamp,
+            modified_at: timestamp,
+        };
+        let record = db
+            .insert_routing_algorithm(algo)
+            .await
+            .to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)?;
+
+        let new_record = record.foreign_into();
+
+        Ok(service_api::ApplicationResponse::Json(new_record))
+    }
+
+    #[cfg(not(feature = "business_profile_routing"))]
+    {
+        let algorithm_str =
+            utils::Encode::<routing_types::RoutingAlgorithm>::encode_to_string_of_json(&algorithm)
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Unable to serialize routing algorithm to string")?;
+
+        let mut algorithm_ref: routing_types::RoutingAlgorithmRef = merchant_account
+            .routing_algorithm
+            .clone()
+            .map(|val| val.parse_value("RoutingAlgorithmRef"))
+            .transpose()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("unable to deserialize routing algorithm ref from merchant account")?
+            .unwrap_or_default();
+        let mut merchant_dictionary =
+            helpers::get_merchant_routing_dictionary(db, &merchant_account.merchant_id).await?;
+
+        utils::when(
+            merchant_dictionary.records.len() >= consts::MAX_ROUTING_CONFIGS_PER_MERCHANT,
+            || {
+                Err(errors::ApiErrorResponse::PreconditionFailed {
+            message: format!("Reached the maximum number of routing configs ({}), please delete some to create new ones", consts::MAX_ROUTING_CONFIGS_PER_MERCHANT),
+        })
+        .into_report()
+            },
+        )?;
+        let timestamp = common_utils::date_time::now_unix_timestamp();
+        let records_are_empty = merchant_dictionary.records.is_empty();
+
+        let new_record = routing_types::RoutingDictionaryRecord {
+            id: algorithm_id.clone(),
+            name: name.clone(),
+            kind: algorithm.get_kind(),
+            description: description.clone(),
+            created_at: timestamp,
+            modified_at: timestamp,
+        };
+        merchant_dictionary.records.push(new_record.clone());
+
+        let new_algorithm_config = configs::ConfigNew {
+            key: algorithm_id.clone(),
+            config: algorithm_str,
+        };
+
+        db.insert_config(new_algorithm_config)
+            .await
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Failed to save new routing algorithm config to DB")?;
+
+        if records_are_empty {
+            merchant_dictionary.active_id = Some(algorithm_id.clone());
+            algorithm_ref.update_algorithm_id(algorithm_id);
+            helpers::update_merchant_active_algorithm_ref(db, &key_store, algorithm_ref).await?;
+        }
+
+        helpers::update_merchant_routing_dictionary(
+            db,
+            &merchant_account.merchant_id,
+            merchant_dictionary,
+        )
+        .await?;
+
+        Ok(service_api::ApplicationResponse::Json(new_record))
+    }
+}
+
+pub async fn link_routing_config(
+    state: AppState,
+    merchant_account: domain::MerchantAccount,
+    #[cfg(not(feature = "business_profile_routing"))] key_store: domain::MerchantKeyStore,
+    algorithm_id: String,
+) -> RouterResponse<routing_types::RoutingDictionaryRecord> {
+    let db = state.store.as_ref();
+    #[cfg(feature = "business_profile_routing")]
+    {
+        let routing_algorithm = db
+            .find_routing_algorithm_by_algorithm_id_merchant_id(
+                &algorithm_id,
+                &merchant_account.merchant_id,
+            )
+            .await
+            .change_context(errors::ApiErrorResponse::ResourceIdNotFound)?;
+
+        let business_profile = core_utils::validate_and_get_business_profile(
+            db,
+            Some(&routing_algorithm.profile_id),
+            &merchant_account.merchant_id,
+        )
+        .await?
+        .get_required_value("BusinessProfile")
+        .change_context(errors::ApiErrorResponse::BusinessProfileNotFound {
+            id: routing_algorithm.profile_id.clone(),
+        })?;
+
+        let mut routing_ref: routing_types::RoutingAlgorithmRef = business_profile
+            .routing_algorithm
+            .clone()
+            .map(|val| val.parse_value("RoutingAlgorithmRef"))
+            .transpose()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("unable to deserialize routing algorithm ref from merchant account")?
+            .unwrap_or_default();
+
+        utils::when(
+            routing_ref.algorithm_id == Some(algorithm_id.clone()),
+            || {
+                Err(errors::ApiErrorResponse::PreconditionFailed {
+                    message: "Algorithm is already active".to_string(),
+                })
+                .into_report()
+            },
+        )?;
+
+        routing_ref.update_algorithm_id(algorithm_id);
+        helpers::update_business_profile_active_algorithm_ref(db, business_profile, routing_ref)
+            .await?;
+
+        Ok(service_api::ApplicationResponse::Json(
+            routing_algorithm.foreign_into(),
+        ))
+    }
+
+    #[cfg(not(feature = "business_profile_routing"))]
+    {
+        let mut routing_ref: routing_types::RoutingAlgorithmRef = merchant_account
+            .routing_algorithm
+            .clone()
+            .map(|val| val.parse_value("RoutingAlgorithmRef"))
+            .transpose()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("unable to deserialize routing algorithm ref from merchant account")?
+            .unwrap_or_default();
+
+        utils::when(
+            routing_ref.algorithm_id == Some(algorithm_id.clone()),
+            || {
+                Err(errors::ApiErrorResponse::PreconditionFailed {
+                    message: "Algorithm is already active".to_string(),
+                })
+                .into_report()
+            },
+        )?;
+        let mut merchant_dictionary =
+            helpers::get_merchant_routing_dictionary(db, &merchant_account.merchant_id).await?;
+
+        let modified_at = common_utils::date_time::now_unix_timestamp();
+        let record = merchant_dictionary
+            .records
+            .iter_mut()
+            .find(|rec| rec.id == algorithm_id)
+            .ok_or(errors::ApiErrorResponse::ResourceIdNotFound)
+            .into_report()
+            .attach_printable("Record with given ID not found for routing config activation")?;
+
+        record.modified_at = modified_at;
+        merchant_dictionary.active_id = Some(record.id.clone());
+        let response = record.clone();
+        routing_ref.update_algorithm_id(algorithm_id);
+        helpers::update_merchant_routing_dictionary(
+            db,
+            &merchant_account.merchant_id,
+            merchant_dictionary,
+        )
+        .await?;
+        helpers::update_merchant_active_algorithm_ref(db, &key_store, routing_ref).await?;
+
+        Ok(service_api::ApplicationResponse::Json(response))
+    }
+}
+
+pub async fn retrieve_routing_config(
+    state: AppState,
+    merchant_account: domain::MerchantAccount,
+    algorithm_id: RoutingAlgorithmId,
+) -> RouterResponse<routing_types::MerchantRoutingAlgorithm> {
+    let db = state.store.as_ref();
+    #[cfg(feature = "business_profile_routing")]
+    {
+        let routing_algorithm = db
+            .find_routing_algorithm_by_algorithm_id_merchant_id(
+                &algorithm_id.0,
+                &merchant_account.merchant_id,
+            )
+            .await
+            .to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)?;
+
+        core_utils::validate_and_get_business_profile(
+            db,
+            Some(&routing_algorithm.profile_id),
+            &merchant_account.merchant_id,
+        )
+        .await?
+        .get_required_value("BusinessProfile")
+        .change_context(errors::ApiErrorResponse::ResourceIdNotFound)?;
+
+        let response = routing_algorithm
+            .foreign_try_into()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("unable to parse routing algorithm")?;
+        Ok(service_api::ApplicationResponse::Json(response))
+    }
+
+    #[cfg(not(feature = "business_profile_routing"))]
+    {
+        let merchant_dictionary =
+            helpers::get_merchant_routing_dictionary(db, &merchant_account.merchant_id).await?;
+
+        let record = merchant_dictionary
+            .records
+            .into_iter()
+            .find(|rec| rec.id == algorithm_id.0)
+            .ok_or(errors::ApiErrorResponse::ResourceIdNotFound)
+            .into_report()
+            .attach_printable("Algorithm with the given ID not found in the merchant dictionary")?;
+
+        let algorithm_config = db
+            .find_config_by_key(&algorithm_id.0)
+            .await
+            .change_context(errors::ApiErrorResponse::ResourceIdNotFound)
+            .attach_printable("Routing config not found in DB")?;
+
+        let algorithm: routing_types::RoutingAlgorithm = algorithm_config
+            .config
+            .parse_struct("RoutingAlgorithm")
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Error deserializing routing algorithm config")?;
+
+        let response = routing_types::MerchantRoutingAlgorithm {
+            id: record.id,
+            name: record.name,
+            description: record.description,
+            algorithm,
+            created_at: record.created_at,
+            modified_at: record.modified_at,
+        };
+
+        Ok(service_api::ApplicationResponse::Json(response))
+    }
+}
+pub async fn unlink_routing_config(
+    state: AppState,
+    merchant_account: domain::MerchantAccount,
+    #[cfg(not(feature = "business_profile_routing"))] key_store: domain::MerchantKeyStore,
+    #[cfg(feature = "business_profile_routing")] request: routing_types::RoutingConfigRequest,
+) -> RouterResponse<routing_types::RoutingDictionaryRecord> {
+    let db = state.store.as_ref();
+    #[cfg(feature = "business_profile_routing")]
+    {
+        let profile_id = request
+            .profile_id
+            .get_required_value("profile_id")
+            .change_context(errors::ApiErrorResponse::MissingRequiredField {
+                field_name: "profile_id",
+            })
+            .attach_printable("Profile_id not provided")?;
+        let business_profile = core_utils::validate_and_get_business_profile(
+            db,
+            Some(&profile_id),
+            &merchant_account.merchant_id,
+        )
+        .await?;
+        match business_profile {
+            Some(business_profile) => {
+                let routing_algo_ref: routing_types::RoutingAlgorithmRef = business_profile
+                    .routing_algorithm
+                    .clone()
+                    .map(|val| val.parse_value("RoutingAlgorithmRef"))
+                    .transpose()
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable(
+                        "unable to deserialize routing algorithm ref from merchant account",
+                    )?
+                    .unwrap_or_default();
+
+                let timestamp = common_utils::date_time::now_unix_timestamp();
+
+                match routing_algo_ref.algorithm_id {
+                    Some(algorithm_id) => {
+                        let routing_algorithm: routing_types::RoutingAlgorithmRef =
+                            routing_types::RoutingAlgorithmRef {
+                                algorithm_id: None,
+                                timestamp,
+                                config_algo_id: routing_algo_ref.config_algo_id.clone(),
+                                surcharge_config_algo_id: routing_algo_ref.surcharge_config_algo_id,
+                            };
+
+                        let record = db
+                            .find_routing_algorithm_by_profile_id_algorithm_id(
+                                &profile_id,
+                                &algorithm_id,
+                            )
+                            .await
+                            .to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)?;
+                        let response = record.foreign_into();
+                        helpers::update_business_profile_active_algorithm_ref(
+                            db,
+                            business_profile,
+                            routing_algorithm,
+                        )
+                        .await?;
+                        Ok(service_api::ApplicationResponse::Json(response))
+                    }
+                    None => Err(errors::ApiErrorResponse::PreconditionFailed {
+                        message: "Algorithm is already inactive".to_string(),
+                    })
+                    .into_report()?,
+                }
+            }
+            None => Err(errors::ApiErrorResponse::InvalidRequestData {
+                message: "The business_profile is not present".to_string(),
+            }
+            .into()),
+        }
+    }
+
+    #[cfg(not(feature = "business_profile_routing"))]
+    {
+        let mut merchant_dictionary =
+            helpers::get_merchant_routing_dictionary(db, &merchant_account.merchant_id).await?;
+
+        let routing_algo_ref: routing_types::RoutingAlgorithmRef = merchant_account
+            .routing_algorithm
+            .clone()
+            .map(|val| val.parse_value("RoutingAlgorithmRef"))
+            .transpose()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("unable to deserialize routing algorithm ref from merchant account")?
+            .unwrap_or_default();
+        let timestamp = common_utils::date_time::now_unix_timestamp();
+
+        utils::when(routing_algo_ref.algorithm_id.is_none(), || {
+            Err(errors::ApiErrorResponse::PreconditionFailed {
+                message: "Algorithm is already inactive".to_string(),
+            })
+            .into_report()
+        })?;
+        let routing_algorithm: routing_types::RoutingAlgorithmRef =
+            routing_types::RoutingAlgorithmRef {
+                algorithm_id: None,
+                timestamp,
+                config_algo_id: routing_algo_ref.config_algo_id.clone(),
+                surcharge_config_algo_id: routing_algo_ref.surcharge_config_algo_id,
+            };
+
+        let active_algorithm_id = merchant_dictionary
+            .active_id
+            .or(routing_algo_ref.algorithm_id.clone())
+            .ok_or(errors::ApiErrorResponse::PreconditionFailed {
+                // When the merchant_dictionary doesn't have any active algorithm and merchant_account doesn't have any routing_algorithm configured
+                message: "Algorithm is already inactive".to_string(),
+            })
+            .into_report()?;
+
+        let record = merchant_dictionary
+            .records
+            .iter_mut()
+            .find(|rec| rec.id == active_algorithm_id)
+            .ok_or(errors::ApiErrorResponse::ResourceIdNotFound)
+            .into_report()
+            .attach_printable("Record with the given ID not found for de-activation")?;
+
+        let response = record.clone();
+
+        merchant_dictionary.active_id = None;
+
+        helpers::update_merchant_routing_dictionary(
+            db,
+            &merchant_account.merchant_id,
+            merchant_dictionary,
+        )
+        .await?;
+
+        let ref_value =
+            Encode::<routing_types::RoutingAlgorithmRef>::encode_to_value(&routing_algorithm)
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Failed converting routing algorithm ref to json value")?;
+
+        let merchant_account_update = storage::MerchantAccountUpdate::Update {
+            merchant_name: None,
+            merchant_details: None,
+            return_url: None,
+            webhook_details: None,
+            sub_merchants_enabled: None,
+            parent_merchant_id: None,
+            enable_payment_response_hash: None,
+            payment_response_hash_key: None,
+            redirect_to_merchant_with_http_post: None,
+            publishable_key: None,
+            locker_id: None,
+            metadata: None,
+            routing_algorithm: Some(ref_value),
+            primary_business_details: None,
+            intent_fulfillment_time: None,
+            frm_routing_algorithm: None,
+            payout_routing_algorithm: None,
+            default_profile: None,
+            payment_link_config: None,
+        };
+
+        db.update_specific_fields_in_merchant(
+            &key_store.merchant_id,
+            merchant_account_update,
+            &key_store,
+        )
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Failed to update routing algorithm ref in merchant account")?;
+
+        Ok(service_api::ApplicationResponse::Json(response))
+    }
+}
+
+pub async fn update_default_routing_config(
+    state: AppState,
+    merchant_account: domain::MerchantAccount,
+    updated_config: Vec<routing_types::RoutableConnectorChoice>,
+) -> RouterResponse<Vec<routing_types::RoutableConnectorChoice>> {
+    let db = state.store.as_ref();
+    let default_config =
+        helpers::get_merchant_default_config(db, &merchant_account.merchant_id).await?;
+
+    utils::when(default_config.len() != updated_config.len(), || {
+        Err(errors::ApiErrorResponse::PreconditionFailed {
+            message: "current config and updated config have different lengths".to_string(),
+        })
+        .into_report()
+    })?;
+
+    let existing_set: FxHashSet<String> =
+        FxHashSet::from_iter(default_config.iter().map(|c| c.to_string()));
+    let updated_set: FxHashSet<String> =
+        FxHashSet::from_iter(updated_config.iter().map(|c| c.to_string()));
+
+    let symmetric_diff: Vec<String> = existing_set
+        .symmetric_difference(&updated_set)
+        .cloned()
+        .collect();
+
+    utils::when(!symmetric_diff.is_empty(), || {
+        Err(errors::ApiErrorResponse::InvalidRequestData {
+            message: format!(
+                "connector mismatch between old and new configs ({})",
+                symmetric_diff.join(", ")
+            ),
+        })
+        .into_report()
+    })?;
+
+    helpers::update_merchant_default_config(
+        db,
+        &merchant_account.merchant_id,
+        updated_config.clone(),
+    )
+    .await?;
+
+    Ok(service_api::ApplicationResponse::Json(updated_config))
+}
+
+pub async fn retrieve_default_routing_config(
+    state: AppState,
+    merchant_account: domain::MerchantAccount,
+) -> RouterResponse<Vec<routing_types::RoutableConnectorChoice>> {
+    let db = state.store.as_ref();
+
+    helpers::get_merchant_default_config(db, &merchant_account.merchant_id)
+        .await
+        .map(service_api::ApplicationResponse::Json)
+}
+
+pub async fn retrieve_linked_routing_config(
+    state: AppState,
+    merchant_account: domain::MerchantAccount,
+    #[cfg(feature = "business_profile_routing")] query_params: RoutingRetrieveLinkQuery,
+) -> RouterResponse<routing_types::LinkedRoutingConfigRetrieveResponse> {
+    let db = state.store.as_ref();
+
+    #[cfg(feature = "business_profile_routing")]
+    {
+        let business_profiles = if let Some(profile_id) = query_params.profile_id {
+            core_utils::validate_and_get_business_profile(
+                db,
+                Some(&profile_id),
+                &merchant_account.merchant_id,
+            )
+            .await?
+            .map(|profile| vec![profile])
+            .get_required_value("BusinessProfile")
+            .change_context(errors::ApiErrorResponse::BusinessProfileNotFound { id: profile_id })?
+        } else {
+            db.list_business_profile_by_merchant_id(&merchant_account.merchant_id)
+                .await
+                .to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)?
+        };
+
+        let mut active_algorithms = Vec::new();
+
+        for business_profile in business_profiles {
+            let routing_ref: routing_types::RoutingAlgorithmRef = business_profile
+                .routing_algorithm
+                .clone()
+                .map(|val| val.parse_value("RoutingAlgorithmRef"))
+                .transpose()
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable(
+                    "unable to deserialize routing algorithm ref from merchant account",
+                )?
+                .unwrap_or_default();
+
+            if let Some(algorithm_id) = routing_ref.algorithm_id {
+                let record = db
+                    .find_routing_algorithm_metadata_by_algorithm_id_profile_id(
+                        &algorithm_id,
+                        &business_profile.profile_id,
+                    )
+                    .await
+                    .to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)?;
+
+                active_algorithms.push(record.foreign_into());
+            }
+        }
+
+        Ok(service_api::ApplicationResponse::Json(
+            routing_types::LinkedRoutingConfigRetrieveResponse::ProfileBased(active_algorithms),
+        ))
+    }
+    #[cfg(not(feature = "business_profile_routing"))]
+    {
+        let merchant_dictionary =
+            helpers::get_merchant_routing_dictionary(db, &merchant_account.merchant_id).await?;
+
+        let algorithm = if let Some(algorithm_id) = merchant_dictionary.active_id {
+            let record = merchant_dictionary
+                .records
+                .into_iter()
+                .find(|rec| rec.id == algorithm_id)
+                .ok_or(errors::ApiErrorResponse::ResourceIdNotFound)
+                .into_report()
+                .attach_printable("record for active algorithm not found in merchant dictionary")?;
+
+            let config = db
+                .find_config_by_key(&algorithm_id)
+                .await
+                .to_not_found_response(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("error finding routing config in db")?;
+
+            let the_algorithm: routing_types::RoutingAlgorithm = config
+                .config
+                .parse_struct("RoutingAlgorithm")
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("unable to parse routing algorithm")?;
+
+            Some(routing_types::MerchantRoutingAlgorithm {
+                id: record.id,
+                name: record.name,
+                description: record.description,
+                algorithm: the_algorithm,
+                created_at: record.created_at,
+                modified_at: record.modified_at,
+            })
+        } else {
+            None
+        };
+
+        let response = routing_types::LinkedRoutingConfigRetrieveResponse::MerchantAccountBased(
+            routing_types::RoutingRetrieveResponse { algorithm },
+        );
+
+        Ok(service_api::ApplicationResponse::Json(response))
+    }
+}
+
+pub async fn retrieve_default_routing_config_for_profiles(
+    state: AppState,
+    merchant_account: domain::MerchantAccount,
+) -> RouterResponse<Vec<routing_types::ProfileDefaultRoutingConfig>> {
+    let db = state.store.as_ref();
+
+    let all_profiles = db
+        .list_business_profile_by_merchant_id(&merchant_account.merchant_id)
+        .await
+        .to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)
+        .attach_printable("error retrieving all business profiles for merchant")?;
+
+    let retrieve_config_futures = all_profiles
+        .iter()
+        .map(|prof| helpers::get_merchant_default_config(db, &prof.profile_id))
+        .collect::<Vec<_>>();
+
+    let configs = futures::future::join_all(retrieve_config_futures)
+        .await
+        .into_iter()
+        .collect::<Result<Vec<_>, _>>()?;
+
+    let default_configs = configs
+        .into_iter()
+        .zip(all_profiles.iter().map(|prof| prof.profile_id.clone()))
+        .map(
+            |(config, profile_id)| routing_types::ProfileDefaultRoutingConfig {
+                profile_id,
+                connectors: config,
+            },
+        )
+        .collect::<Vec<_>>();
+
+    Ok(service_api::ApplicationResponse::Json(default_configs))
+}
+
+pub async fn update_default_routing_config_for_profile(
+    state: AppState,
+    merchant_account: domain::MerchantAccount,
+    updated_config: Vec<routing_types::RoutableConnectorChoice>,
+    profile_id: String,
+) -> RouterResponse<routing_types::ProfileDefaultRoutingConfig> {
+    let db = state.store.as_ref();
+
+    let business_profile = core_utils::validate_and_get_business_profile(
+        db,
+        Some(&profile_id),
+        &merchant_account.merchant_id,
+    )
+    .await?
+    .get_required_value("BusinessProfile")
+    .change_context(errors::ApiErrorResponse::BusinessProfileNotFound { id: profile_id })?;
+    let default_config =
+        helpers::get_merchant_default_config(db, &business_profile.profile_id).await?;
+
+    utils::when(default_config.len() != updated_config.len(), || {
+        Err(errors::ApiErrorResponse::PreconditionFailed {
+            message: "current config and updated config have different lengths".to_string(),
+        })
+        .into_report()
+    })?;
+
+    let existing_set = FxHashSet::from_iter(default_config.iter().map(|c| {
+        (
+            c.connector.to_string(),
+            #[cfg(feature = "connector_choice_mca_id")]
+            c.merchant_connector_id.as_ref(),
+            #[cfg(not(feature = "connector_choice_mca_id"))]
+            c.sub_label.as_ref(),
+        )
+    }));
+
+    let updated_set = FxHashSet::from_iter(updated_config.iter().map(|c| {
+        (
+            c.connector.to_string(),
+            #[cfg(feature = "connector_choice_mca_id")]
+            c.merchant_connector_id.as_ref(),
+            #[cfg(not(feature = "connector_choice_mca_id"))]
+            c.sub_label.as_ref(),
+        )
+    }));
+
+    let symmetric_diff = existing_set
+        .symmetric_difference(&updated_set)
+        .cloned()
+        .collect::<Vec<_>>();
+
+    utils::when(!symmetric_diff.is_empty(), || {
+        let error_str = symmetric_diff
+            .into_iter()
+            .map(|(connector, ident)| format!("'{connector}:{ident:?}'"))
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        Err(errors::ApiErrorResponse::InvalidRequestData {
+            message: format!("connector mismatch between old and new configs ({error_str})"),
+        })
+        .into_report()
+    })?;
+
+    helpers::update_merchant_default_config(
+        db,
+        &business_profile.profile_id,
+        updated_config.clone(),
+    )
+    .await?;
+
+    Ok(service_api::ApplicationResponse::Json(
+        routing_types::ProfileDefaultRoutingConfig {
+            profile_id: business_profile.profile_id,
+            connectors: updated_config,
+        },
+    ))
+}
diff --git a/crates/router/src/core/routing/helpers.rs b/crates/router/src/core/routing/helpers.rs
new file mode 100644
index 000000000000..6eec39f53bc6
--- /dev/null
+++ b/crates/router/src/core/routing/helpers.rs
@@ -0,0 +1,479 @@
+//! Analysis for usage of all helper functions for use case of routing
+//!
+//! Functions that are used to perform the retrieval of merchant's
+//! routing dict, configs, defaults
+use api_models::routing as routing_types;
+use common_utils::ext_traits::Encode;
+use diesel_models::{
+    business_profile::{BusinessProfile, BusinessProfileUpdateInternal},
+    configs,
+};
+use error_stack::ResultExt;
+use rustc_hash::FxHashSet;
+
+use crate::{
+    core::errors::{self, RouterResult},
+    db::StorageInterface,
+    types::{domain, storage},
+    utils::{self, StringExt},
+};
+
+/// provides the complete merchant routing dictionary that is basically a list of all the routing
+/// configs a merchant configured with an active_id field that specifies the current active routing
+/// config
+pub async fn get_merchant_routing_dictionary(
+    db: &dyn StorageInterface,
+    merchant_id: &str,
+) -> RouterResult<routing_types::RoutingDictionary> {
+    let key = get_routing_dictionary_key(merchant_id);
+    let maybe_dict = db.find_config_by_key(&key).await;
+
+    match maybe_dict {
+        Ok(config) => config
+            .config
+            .parse_struct("RoutingDictionary")
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Merchant routing dictionary has invalid structure"),
+
+        Err(e) if e.current_context().is_db_not_found() => {
+            let new_dictionary = routing_types::RoutingDictionary {
+                merchant_id: merchant_id.to_string(),
+                active_id: None,
+                records: Vec::new(),
+            };
+
+            let serialized =
+                utils::Encode::<routing_types::RoutingDictionary>::encode_to_string_of_json(
+                    &new_dictionary,
+                )
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Error serializing newly created merchant dictionary")?;
+
+            let new_config = configs::ConfigNew {
+                key,
+                config: serialized,
+            };
+
+            db.insert_config(new_config)
+                .await
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Error inserting new routing dictionary for merchant")?;
+
+            Ok(new_dictionary)
+        }
+
+        Err(e) => Err(e)
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Error fetching routing dictionary for merchant"),
+    }
+}
+
+/// Provides us with all the configured configs of the Merchant in the ascending time configured
+/// manner and chooses the first of them
+pub async fn get_merchant_default_config(
+    db: &dyn StorageInterface,
+    merchant_id: &str,
+) -> RouterResult<Vec<routing_types::RoutableConnectorChoice>> {
+    let key = get_default_config_key(merchant_id);
+    let maybe_config = db.find_config_by_key(&key).await;
+
+    match maybe_config {
+        Ok(config) => config
+            .config
+            .parse_struct("Vec<RoutableConnectors>")
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Merchant default config has invalid structure"),
+
+        Err(e) if e.current_context().is_db_not_found() => {
+            let new_config_conns = Vec::<routing_types::RoutableConnectorChoice>::new();
+            let serialized =
+                utils::Encode::<Vec<routing_types::RoutableConnectorChoice>>::encode_to_string_of_json(
+                    &new_config_conns,
+                )
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable(
+                    "Error while creating and serializing new merchant default config",
+                )?;
+
+            let new_config = configs::ConfigNew {
+                key,
+                config: serialized,
+            };
+
+            db.insert_config(new_config)
+                .await
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Error inserting new default routing config into DB")?;
+
+            Ok(new_config_conns)
+        }
+
+        Err(e) => Err(e)
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Error fetching default config for merchant"),
+    }
+}
+
+/// Merchant's already created config can be updated and this change will be reflected
+/// in DB as well for the particular updated config
+pub async fn update_merchant_default_config(
+    db: &dyn StorageInterface,
+    merchant_id: &str,
+    connectors: Vec<routing_types::RoutableConnectorChoice>,
+) -> RouterResult<()> {
+    let key = get_default_config_key(merchant_id);
+    let config_str =
+        Encode::<Vec<routing_types::RoutableConnectorChoice>>::encode_to_string_of_json(
+            &connectors,
+        )
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Unable to serialize merchant default routing config during update")?;
+
+    let config_update = configs::ConfigUpdate::Update {
+        config: Some(config_str),
+    };
+
+    db.update_config_by_key(&key, config_update)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Error updating the default routing config in DB")?;
+
+    Ok(())
+}
+
+pub async fn update_merchant_routing_dictionary(
+    db: &dyn StorageInterface,
+    merchant_id: &str,
+    dictionary: routing_types::RoutingDictionary,
+) -> RouterResult<()> {
+    let key = get_routing_dictionary_key(merchant_id);
+    let dictionary_str =
+        Encode::<routing_types::RoutingDictionary>::encode_to_string_of_json(&dictionary)
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Unable to serialize routing dictionary during update")?;
+
+    let config_update = configs::ConfigUpdate::Update {
+        config: Some(dictionary_str),
+    };
+
+    db.update_config_by_key(&key, config_update)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Error saving routing dictionary to DB")?;
+
+    Ok(())
+}
+
+pub async fn update_routing_algorithm(
+    db: &dyn StorageInterface,
+    algorithm_id: String,
+    algorithm: routing_types::RoutingAlgorithm,
+) -> RouterResult<()> {
+    let algorithm_str =
+        Encode::<routing_types::RoutingAlgorithm>::encode_to_string_of_json(&algorithm)
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Unable to serialize routing algorithm to string")?;
+
+    let config_update = configs::ConfigUpdate::Update {
+        config: Some(algorithm_str),
+    };
+
+    db.update_config_by_key(&algorithm_id, config_update)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Error updating the routing algorithm in DB")?;
+
+    Ok(())
+}
+
+/// This will help make one of all configured algorithms to be in active state for a particular
+/// merchant
+pub async fn update_merchant_active_algorithm_ref(
+    db: &dyn StorageInterface,
+    key_store: &domain::MerchantKeyStore,
+    algorithm_id: routing_types::RoutingAlgorithmRef,
+) -> RouterResult<()> {
+    let ref_value = Encode::<routing_types::RoutingAlgorithmRef>::encode_to_value(&algorithm_id)
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Failed converting routing algorithm ref to json value")?;
+
+    let merchant_account_update = storage::MerchantAccountUpdate::Update {
+        merchant_name: None,
+        merchant_details: None,
+        return_url: None,
+        webhook_details: None,
+        sub_merchants_enabled: None,
+        parent_merchant_id: None,
+        enable_payment_response_hash: None,
+        payment_response_hash_key: None,
+        redirect_to_merchant_with_http_post: None,
+        publishable_key: None,
+        locker_id: None,
+        metadata: None,
+        routing_algorithm: Some(ref_value),
+        primary_business_details: None,
+        intent_fulfillment_time: None,
+        frm_routing_algorithm: None,
+        payout_routing_algorithm: None,
+        default_profile: None,
+        payment_link_config: None,
+    };
+
+    db.update_specific_fields_in_merchant(
+        &key_store.merchant_id,
+        merchant_account_update,
+        key_store,
+    )
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Failed to update routing algorithm ref in merchant account")?;
+
+    Ok(())
+}
+
+pub async fn update_business_profile_active_algorithm_ref(
+    db: &dyn StorageInterface,
+    current_business_profile: BusinessProfile,
+    algorithm_id: routing_types::RoutingAlgorithmRef,
+) -> RouterResult<()> {
+    let ref_val = Encode::<routing_types::RoutingAlgorithmRef>::encode_to_value(&algorithm_id)
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Failed to convert routing ref to value")?;
+
+    let business_profile_update = BusinessProfileUpdateInternal {
+        profile_name: None,
+        return_url: None,
+        enable_payment_response_hash: None,
+        payment_response_hash_key: None,
+        redirect_to_merchant_with_http_post: None,
+        webhook_details: None,
+        metadata: None,
+        routing_algorithm: Some(ref_val),
+        intent_fulfillment_time: None,
+        frm_routing_algorithm: None,
+        payout_routing_algorithm: None,
+        applepay_verified_domains: None,
+        modified_at: None,
+        is_recon_enabled: None,
+    };
+    db.update_business_profile_by_profile_id(current_business_profile, business_profile_update)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Failed to update routing algorithm ref in business profile")?;
+    Ok(())
+}
+
+pub async fn get_merchant_connector_agnostic_mandate_config(
+    db: &dyn StorageInterface,
+    merchant_id: &str,
+) -> RouterResult<Vec<routing_types::DetailedConnectorChoice>> {
+    let key = get_pg_agnostic_mandate_config_key(merchant_id);
+    let maybe_config = db.find_config_by_key(&key).await;
+
+    match maybe_config {
+        Ok(config) => config
+            .config
+            .parse_struct("Vec<DetailedConnectorChoice>")
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("pg agnostic mandate config has invalid structure"),
+
+        Err(e) if e.current_context().is_db_not_found() => {
+            let new_mandate_config: Vec<routing_types::DetailedConnectorChoice> = Vec::new();
+
+            let serialized =
+                utils::Encode::<Vec<routing_types::DetailedConnectorChoice>>::encode_to_string_of_json(
+                    &new_mandate_config,
+                )
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("error serializing newly created pg agnostic mandate config")?;
+
+            let new_config = configs::ConfigNew {
+                key,
+                config: serialized,
+            };
+
+            db.insert_config(new_config)
+                .await
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("error inserting new pg agnostic mandate config in db")?;
+
+            Ok(new_mandate_config)
+        }
+
+        Err(e) => Err(e)
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("error fetching pg agnostic mandate config for merchant from db"),
+    }
+}
+
+pub async fn update_merchant_connector_agnostic_mandate_config(
+    db: &dyn StorageInterface,
+    merchant_id: &str,
+    mandate_config: Vec<routing_types::DetailedConnectorChoice>,
+) -> RouterResult<Vec<routing_types::DetailedConnectorChoice>> {
+    let key = get_pg_agnostic_mandate_config_key(merchant_id);
+    let mandate_config_str =
+        Encode::<Vec<routing_types::DetailedConnectorChoice>>::encode_to_string_of_json(
+            &mandate_config,
+        )
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("unable to serialize pg agnostic mandate config during update")?;
+
+    let config_update = configs::ConfigUpdate::Update {
+        config: Some(mandate_config_str),
+    };
+
+    db.update_config_by_key(&key, config_update)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("error saving pg agnostic mandate config to db")?;
+
+    Ok(mandate_config)
+}
+
+pub async fn validate_connectors_in_routing_config(
+    db: &dyn StorageInterface,
+    key_store: &domain::MerchantKeyStore,
+    merchant_id: &str,
+    profile_id: &str,
+    routing_algorithm: &routing_types::RoutingAlgorithm,
+) -> RouterResult<()> {
+    let all_mcas = db
+        .find_merchant_connector_account_by_merchant_id_and_disabled_list(
+            merchant_id,
+            true,
+            key_store,
+        )
+        .await
+        .change_context(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
+            id: merchant_id.to_string(),
+        })?;
+
+    #[cfg(feature = "connector_choice_mca_id")]
+    let name_mca_id_set = all_mcas
+        .iter()
+        .filter(|mca| mca.profile_id.as_deref() == Some(profile_id))
+        .map(|mca| (&mca.connector_name, &mca.merchant_connector_id))
+        .collect::<FxHashSet<_>>();
+
+    let name_set = all_mcas
+        .iter()
+        .filter(|mca| mca.profile_id.as_deref() == Some(profile_id))
+        .map(|mca| &mca.connector_name)
+        .collect::<FxHashSet<_>>();
+
+    #[cfg(feature = "connector_choice_mca_id")]
+    let check_connector_choice = |choice: &routing_types::RoutableConnectorChoice| {
+        if let Some(ref mca_id) = choice.merchant_connector_id {
+            error_stack::ensure!(
+                name_mca_id_set.contains(&(&choice.connector.to_string(), mca_id)),
+                errors::ApiErrorResponse::InvalidRequestData {
+                    message: format!(
+                        "connector with name '{}' and merchant connector account id '{}' not found for the given profile",
+                        choice.connector,
+                        mca_id,
+                    )
+                }
+            );
+        } else {
+            error_stack::ensure!(
+                name_set.contains(&choice.connector.to_string()),
+                errors::ApiErrorResponse::InvalidRequestData {
+                    message: format!(
+                        "connector with name '{}' not found for the given profile",
+                        choice.connector,
+                    )
+                }
+            );
+        }
+
+        Ok(())
+    };
+
+    #[cfg(not(feature = "connector_choice_mca_id"))]
+    let check_connector_choice = |choice: &routing_types::RoutableConnectorChoice| {
+        error_stack::ensure!(
+            name_set.contains(&choice.connector.to_string()),
+            errors::ApiErrorResponse::InvalidRequestData {
+                message: format!(
+                    "connector with name '{}' not found for the given profile",
+                    choice.connector,
+                )
+            }
+        );
+
+        Ok(())
+    };
+
+    match routing_algorithm {
+        routing_types::RoutingAlgorithm::Single(choice) => {
+            check_connector_choice(choice)?;
+        }
+
+        routing_types::RoutingAlgorithm::Priority(list) => {
+            for choice in list {
+                check_connector_choice(choice)?;
+            }
+        }
+
+        routing_types::RoutingAlgorithm::VolumeSplit(splits) => {
+            for split in splits {
+                check_connector_choice(&split.connector)?;
+            }
+        }
+
+        routing_types::RoutingAlgorithm::Advanced(program) => {
+            let check_connector_selection =
+                |selection: &routing_types::ConnectorSelection| -> RouterResult<()> {
+                    match selection {
+                        routing_types::ConnectorSelection::VolumeSplit(splits) => {
+                            for split in splits {
+                                check_connector_choice(&split.connector)?;
+                            }
+                        }
+
+                        routing_types::ConnectorSelection::Priority(list) => {
+                            for choice in list {
+                                check_connector_choice(choice)?;
+                            }
+                        }
+                    }
+
+                    Ok(())
+                };
+
+            check_connector_selection(&program.default_selection)?;
+
+            for rule in &program.rules {
+                check_connector_selection(&rule.connector_selection)?;
+            }
+        }
+    }
+
+    Ok(())
+}
+
+/// Provides the identifier for the specific merchant's routing_dictionary_key
+#[inline(always)]
+pub fn get_routing_dictionary_key(merchant_id: &str) -> String {
+    format!("routing_dict_{merchant_id}")
+}
+
+/// Provides the identifier for the specific merchant's agnostic_mandate_config
+#[inline(always)]
+pub fn get_pg_agnostic_mandate_config_key(merchant_id: &str) -> String {
+    format!("pg_agnostic_mandate_{merchant_id}")
+}
+
+/// Provides the identifier for the specific merchant's default_config
+#[inline(always)]
+pub fn get_default_config_key(merchant_id: &str) -> String {
+    format!("routing_default_{merchant_id}")
+}
+pub fn get_payment_config_routing_id(merchant_id: &str) -> String {
+    format!("payment_config_id_{merchant_id}")
+}
+
+pub fn get_payment_method_surcharge_routing_id(merchant_id: &str) -> String {
+    format!("payment_method_surcharge_id_{merchant_id}")
+}
diff --git a/crates/router/src/core/routing/transformers.rs b/crates/router/src/core/routing/transformers.rs
new file mode 100644
index 000000000000..e5f1f1e1d5f0
--- /dev/null
+++ b/crates/router/src/core/routing/transformers.rs
@@ -0,0 +1,86 @@
+use api_models::routing::{
+    MerchantRoutingAlgorithm, RoutingAlgorithm as Algorithm, RoutingAlgorithmKind,
+    RoutingDictionaryRecord,
+};
+use common_utils::ext_traits::ValueExt;
+use diesel_models::{
+    enums as storage_enums,
+    routing_algorithm::{RoutingAlgorithm, RoutingProfileMetadata},
+};
+
+use crate::{
+    core::errors,
+    types::transformers::{ForeignFrom, ForeignInto, ForeignTryFrom},
+};
+
+impl ForeignFrom<RoutingProfileMetadata> for RoutingDictionaryRecord {
+    fn foreign_from(value: RoutingProfileMetadata) -> Self {
+        Self {
+            id: value.algorithm_id,
+            #[cfg(feature = "business_profile_routing")]
+            profile_id: value.profile_id,
+            name: value.name,
+
+            kind: value.kind.foreign_into(),
+            description: value.description.unwrap_or_default(),
+            created_at: value.created_at.assume_utc().unix_timestamp(),
+            modified_at: value.modified_at.assume_utc().unix_timestamp(),
+        }
+    }
+}
+
+impl ForeignFrom<RoutingAlgorithm> for RoutingDictionaryRecord {
+    fn foreign_from(value: RoutingAlgorithm) -> Self {
+        Self {
+            id: value.algorithm_id,
+            #[cfg(feature = "business_profile_routing")]
+            profile_id: value.profile_id,
+            name: value.name,
+            kind: value.kind.foreign_into(),
+            description: value.description.unwrap_or_default(),
+            created_at: value.created_at.assume_utc().unix_timestamp(),
+            modified_at: value.modified_at.assume_utc().unix_timestamp(),
+        }
+    }
+}
+
+impl ForeignTryFrom<RoutingAlgorithm> for MerchantRoutingAlgorithm {
+    type Error = error_stack::Report<errors::ParsingError>;
+
+    fn foreign_try_from(value: RoutingAlgorithm) -> Result<Self, Self::Error> {
+        Ok(Self {
+            id: value.algorithm_id,
+            name: value.name,
+            #[cfg(feature = "business_profile_routing")]
+            profile_id: value.profile_id,
+            description: value.description.unwrap_or_default(),
+            algorithm: value
+                .algorithm_data
+                .parse_value::<Algorithm>("RoutingAlgorithm")?,
+            created_at: value.created_at.assume_utc().unix_timestamp(),
+            modified_at: value.modified_at.assume_utc().unix_timestamp(),
+        })
+    }
+}
+
+impl ForeignFrom<storage_enums::RoutingAlgorithmKind> for RoutingAlgorithmKind {
+    fn foreign_from(value: storage_enums::RoutingAlgorithmKind) -> Self {
+        match value {
+            storage_enums::RoutingAlgorithmKind::Single => Self::Single,
+            storage_enums::RoutingAlgorithmKind::Priority => Self::Priority,
+            storage_enums::RoutingAlgorithmKind::VolumeSplit => Self::VolumeSplit,
+            storage_enums::RoutingAlgorithmKind::Advanced => Self::Advanced,
+        }
+    }
+}
+
+impl ForeignFrom<RoutingAlgorithmKind> for storage_enums::RoutingAlgorithmKind {
+    fn foreign_from(value: RoutingAlgorithmKind) -> Self {
+        match value {
+            RoutingAlgorithmKind::Single => Self::Single,
+            RoutingAlgorithmKind::Priority => Self::Priority,
+            RoutingAlgorithmKind::VolumeSplit => Self::VolumeSplit,
+            RoutingAlgorithmKind::Advanced => Self::Advanced,
+        }
+    }
+}
diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs
new file mode 100644
index 000000000000..710dc9281bfa
--- /dev/null
+++ b/crates/router/src/core/user.rs
@@ -0,0 +1,81 @@
+use api_models::user as api;
+use diesel_models::enums::UserStatus;
+use error_stack::IntoReport;
+use masking::{ExposeInterface, Secret};
+use router_env::env;
+
+use super::errors::{UserErrors, UserResponse};
+use crate::{
+    consts::user as consts, routes::AppState, services::ApplicationResponse, types::domain,
+};
+
+pub async fn connect_account(
+    state: AppState,
+    request: api::ConnectAccountRequest,
+) -> UserResponse<api::ConnectAccountResponse> {
+    let find_user = state
+        .store
+        .find_user_by_email(request.email.clone().expose().expose().as_str())
+        .await;
+
+    if let Ok(found_user) = find_user {
+        let user_from_db: domain::UserFromStorage = found_user.into();
+
+        user_from_db.compare_password(request.password)?;
+
+        let user_role = user_from_db.get_role_from_db(state.clone()).await?;
+        let jwt_token = user_from_db
+            .get_jwt_auth_token(state.clone(), user_role.org_id)
+            .await?;
+
+        return Ok(ApplicationResponse::Json(api::ConnectAccountResponse {
+            token: Secret::new(jwt_token),
+            merchant_id: user_role.merchant_id,
+            name: user_from_db.get_name(),
+            email: user_from_db.get_email(),
+            verification_days_left: None,
+            user_role: user_role.role_id,
+            user_id: user_from_db.get_user_id().to_string(),
+        }));
+    } else if find_user
+        .map_err(|e| e.current_context().is_db_not_found())
+        .err()
+        .unwrap_or(false)
+    {
+        if matches!(env::which(), env::Env::Production) {
+            return Err(UserErrors::InvalidCredentials).into_report();
+        }
+
+        let new_user = domain::NewUser::try_from(request)?;
+        let _ = new_user
+            .get_new_merchant()
+            .get_new_organization()
+            .insert_org_in_db(state.clone())
+            .await?;
+        let user_from_db = new_user
+            .insert_user_and_merchant_in_db(state.clone())
+            .await?;
+        let user_role = new_user
+            .insert_user_role_in_db(
+                state.clone(),
+                consts::ROLE_ID_ORGANIZATION_ADMIN.to_string(),
+                UserStatus::Active,
+            )
+            .await?;
+        let jwt_token = user_from_db
+            .get_jwt_auth_token(state.clone(), user_role.org_id)
+            .await?;
+
+        return Ok(ApplicationResponse::Json(api::ConnectAccountResponse {
+            token: Secret::new(jwt_token),
+            merchant_id: user_role.merchant_id,
+            name: user_from_db.get_name(),
+            email: user_from_db.get_email(),
+            verification_days_left: None,
+            user_role: user_role.role_id,
+            user_id: user_from_db.get_user_id().to_string(),
+        }));
+    } else {
+        Err(UserErrors::InternalServerError.into())
+    }
+}
diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs
index beedfb98bc22..fb3dc3e7d281 100644
--- a/crates/router/src/core/utils.rs
+++ b/crates/router/src/core/utils.rs
@@ -1,10 +1,18 @@
 use std::{marker::PhantomData, str::FromStr};
 
-use api_models::enums::{DisputeStage, DisputeStatus};
+use api_models::{
+    enums::{DisputeStage, DisputeStatus},
+    payment_methods::{SurchargeDetailsResponse, SurchargeMetadata},
+};
 #[cfg(feature = "payouts")]
 use common_utils::{crypto::Encryptable, pii::Email};
-use common_utils::{errors::CustomResult, ext_traits::AsyncExt};
+use common_utils::{
+    errors::CustomResult,
+    ext_traits::{AsyncExt, Encode},
+};
 use error_stack::{report, IntoReport, ResultExt};
+use euclid::enums as euclid_enums;
+use redis_interface::errors::RedisError;
 use router_env::{instrument, tracing};
 use uuid::Uuid;
 
@@ -63,6 +71,7 @@ pub async fn get_mca_for_payout<'a>(
                 key_store,
                 &profile_id,
                 connector_id,
+                payout_attempt.merchant_connector_id.as_ref(),
             )
             .await?;
             Ok((merchant_connector_account, profile_id))
@@ -222,6 +231,7 @@ pub async fn construct_refund_router_data<'a, F>(
         key_store,
         &profile_id,
         connector_id,
+        payment_attempt.merchant_connector_id.as_ref(),
     )
     .await?;
 
@@ -508,6 +518,7 @@ pub async fn construct_accept_dispute_router_data<'a>(
         key_store,
         &profile_id,
         &dispute.connector,
+        payment_attempt.merchant_connector_id.as_ref(),
     )
     .await?;
 
@@ -597,6 +608,7 @@ pub async fn construct_submit_evidence_router_data<'a>(
         key_store,
         &profile_id,
         connector_id,
+        payment_attempt.merchant_connector_id.as_ref(),
     )
     .await?;
 
@@ -684,8 +696,10 @@ pub async fn construct_upload_file_router_data<'a>(
         key_store,
         &profile_id,
         connector_id,
+        payment_attempt.merchant_connector_id.as_ref(),
     )
     .await?;
+
     let test_mode: Option<bool> = merchant_connector_account.is_test_mode_on();
     let auth_type: types::ConnectorAuthType = merchant_connector_account
         .get_connector_account_details()
@@ -774,6 +788,7 @@ pub async fn construct_defend_dispute_router_data<'a>(
         key_store,
         &profile_id,
         connector_id,
+        payment_attempt.merchant_connector_id.as_ref(),
     )
     .await?;
 
@@ -858,6 +873,7 @@ pub async fn construct_retrieve_file_router_data<'a>(
         key_store,
         profile_id,
         connector_id,
+        file_metadata.merchant_connector_id.as_ref(),
     )
     .await?;
 
@@ -1065,3 +1081,65 @@ pub fn get_flow_name<F>() -> RouterResult<String> {
         .attach_printable("Flow stringify failed")?
         .to_string())
 }
+
+pub async fn persist_individual_surcharge_details_in_redis(
+    state: &AppState,
+    merchant_account: &domain::MerchantAccount,
+    surcharge_metadata: &SurchargeMetadata,
+) -> RouterResult<()> {
+    if !surcharge_metadata.is_empty_result() {
+        let redis_conn = state
+            .store
+            .get_redis_conn()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Failed to get redis connection")?;
+        let redis_key = SurchargeMetadata::get_surcharge_metadata_redis_key(
+            &surcharge_metadata.payment_attempt_id,
+        );
+
+        let mut value_list = Vec::with_capacity(surcharge_metadata.get_surcharge_results_size());
+        for (key, value) in surcharge_metadata
+            .get_individual_surcharge_key_value_pairs()
+            .into_iter()
+        {
+            value_list.push((
+                key,
+                Encode::<SurchargeDetailsResponse>::encode_to_string_of_json(&value)
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("Failed to encode to string of json")?,
+            ));
+        }
+        let intent_fulfillment_time = merchant_account
+            .intent_fulfillment_time
+            .unwrap_or(consts::DEFAULT_FULFILLMENT_TIME);
+        redis_conn
+            .set_hash_fields(&redis_key, value_list, Some(intent_fulfillment_time))
+            .await
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Failed to write to redis")?;
+    }
+    Ok(())
+}
+
+pub async fn get_individual_surcharge_detail_from_redis(
+    state: &AppState,
+    payment_method: &euclid_enums::PaymentMethod,
+    payment_method_type: &euclid_enums::PaymentMethodType,
+    card_network: Option<euclid_enums::CardNetwork>,
+    payment_attempt_id: &str,
+) -> CustomResult<SurchargeDetailsResponse, RedisError> {
+    let redis_conn = state
+        .store
+        .get_redis_conn()
+        .attach_printable("Failed to get redis connection")?;
+    let redis_key = SurchargeMetadata::get_surcharge_metadata_redis_key(payment_attempt_id);
+    let value_key = SurchargeMetadata::get_surcharge_details_redis_hashset_key(
+        payment_method,
+        payment_method_type,
+        card_network.as_ref(),
+    );
+
+    redis_conn
+        .get_hash_field_and_deserialize(&redis_key, &value_key, "SurchargeDetailsResponse")
+        .await
+}
diff --git a/crates/router/src/core/verification.rs b/crates/router/src/core/verification.rs
index fa700b4cd663..e643e0455b8b 100644
--- a/crates/router/src/core/verification.rs
+++ b/crates/router/src/core/verification.rs
@@ -1,5 +1,4 @@
 pub mod utils;
-use actix_web::web;
 use api_models::verifications::{self, ApplepayMerchantResponse};
 use common_utils::{errors::CustomResult, ext_traits::Encode};
 use error_stack::ResultExt;
@@ -18,7 +17,7 @@ const APPLEPAY_INTERNAL_MERCHANT_NAME: &str = "Applepay_merchant";
 pub async fn verify_merchant_creds_for_applepay(
     state: AppState,
     _req: &actix_web::HttpRequest,
-    body: web::Json<verifications::ApplepayMerchantVerificationRequest>,
+    body: verifications::ApplepayMerchantVerificationRequest,
     kms_config: &kms::KmsConfig,
     merchant_id: String,
 ) -> CustomResult<
diff --git a/crates/router/src/core/webhooks.rs b/crates/router/src/core/webhooks.rs
index 2e763751f463..db53a3b56a15 100644
--- a/crates/router/src/core/webhooks.rs
+++ b/crates/router/src/core/webhooks.rs
@@ -46,6 +46,7 @@ pub async fn payments_incoming_webhook_flow<
 >(
     state: AppState,
     merchant_account: domain::MerchantAccount,
+    business_profile: diesel_models::business_profile::BusinessProfile,
     key_store: domain::MerchantKeyStore,
     webhook_details: api::IncomingWebhookDetails,
     source_verified: bool,
@@ -78,28 +79,35 @@ pub async fn payments_incoming_webhook_flow<
                 .perform_locking_action(&state, merchant_account.merchant_id.to_string())
                 .await?;
 
-            let response =
-                payments::payments_core::<api::PSync, api::PaymentsResponse, _, _, _, Ctx>(
-                    state.clone(),
-                    merchant_account.clone(),
-                    key_store,
-                    payments::operations::PaymentStatus,
-                    api::PaymentsRetrieveRequest {
-                        resource_id: id,
-                        merchant_id: Some(merchant_account.merchant_id.clone()),
-                        force_sync: true,
-                        connector: None,
-                        param: None,
-                        merchant_connector_details: None,
-                        client_secret: None,
-                        expand_attempts: None,
-                        expand_captures: None,
-                    },
-                    services::AuthFlow::Merchant,
-                    consume_or_trigger_flow,
-                    HeaderPayload::default(),
-                )
-                .await;
+            let response = Box::pin(payments::payments_core::<
+                api::PSync,
+                api::PaymentsResponse,
+                _,
+                _,
+                _,
+                Ctx,
+            >(
+                state.clone(),
+                merchant_account.clone(),
+                key_store,
+                payments::operations::PaymentStatus,
+                api::PaymentsRetrieveRequest {
+                    resource_id: id,
+                    merchant_id: Some(merchant_account.merchant_id.clone()),
+                    force_sync: true,
+                    connector: None,
+                    param: None,
+                    merchant_connector_details: None,
+                    client_secret: None,
+                    expand_attempts: None,
+                    expand_captures: None,
+                },
+                services::AuthFlow::Merchant,
+                consume_or_trigger_flow,
+                None,
+                HeaderPayload::default(),
+            ))
+            .await;
 
             lock_action
                 .free_lock_action(&state, merchant_account.merchant_id.to_owned())
@@ -156,6 +164,7 @@ pub async fn payments_incoming_webhook_flow<
                 create_event_and_trigger_outgoing_webhook::<W>(
                     state,
                     merchant_account,
+                    business_profile,
                     outgoing_event_type,
                     enums::EventClass::Payments,
                     None,
@@ -178,9 +187,11 @@ pub async fn payments_incoming_webhook_flow<
 }
 
 #[instrument(skip_all)]
+#[allow(clippy::too_many_arguments)]
 pub async fn refunds_incoming_webhook_flow<W: types::OutgoingWebhookType>(
     state: AppState,
     merchant_account: domain::MerchantAccount,
+    business_profile: diesel_models::business_profile::BusinessProfile,
     key_store: domain::MerchantKeyStore,
     webhook_details: api::IncomingWebhookDetails,
     connector_name: &str,
@@ -269,6 +280,7 @@ pub async fn refunds_incoming_webhook_flow<W: types::OutgoingWebhookType>(
         create_event_and_trigger_outgoing_webhook::<W>(
             state,
             merchant_account,
+            business_profile,
             outgoing_event_type,
             enums::EventClass::Refunds,
             None,
@@ -361,6 +373,7 @@ pub async fn get_or_update_dispute_object(
                 connector_updated_at: dispute_details.updated_at,
                 profile_id: None,
                 evidence: None,
+                merchant_connector_id: payment_attempt.merchant_connector_id.clone(),
             };
             state
                 .store
@@ -403,6 +416,7 @@ pub async fn get_or_update_dispute_object(
 pub async fn mandates_incoming_webhook_flow<W: types::OutgoingWebhookType>(
     state: AppState,
     merchant_account: domain::MerchantAccount,
+    business_profile: diesel_models::business_profile::BusinessProfile,
     webhook_details: api::IncomingWebhookDetails,
     source_verified: bool,
     event_type: api_models::webhooks::IncomingWebhookEvent,
@@ -454,6 +468,7 @@ pub async fn mandates_incoming_webhook_flow<W: types::OutgoingWebhookType>(
             create_event_and_trigger_outgoing_webhook::<W>(
                 state,
                 merchant_account,
+                business_profile,
                 outgoing_event_type,
                 enums::EventClass::Mandates,
                 None,
@@ -473,10 +488,12 @@ pub async fn mandates_incoming_webhook_flow<W: types::OutgoingWebhookType>(
     }
 }
 
+#[allow(clippy::too_many_arguments)]
 #[instrument(skip_all)]
 pub async fn disputes_incoming_webhook_flow<W: types::OutgoingWebhookType>(
     state: AppState,
     merchant_account: domain::MerchantAccount,
+    business_profile: diesel_models::business_profile::BusinessProfile,
     webhook_details: api::IncomingWebhookDetails,
     source_verified: bool,
     connector: &(dyn api::Connector + Sync),
@@ -517,6 +534,7 @@ pub async fn disputes_incoming_webhook_flow<W: types::OutgoingWebhookType>(
         create_event_and_trigger_outgoing_webhook::<W>(
             state,
             merchant_account,
+            business_profile,
             event_type,
             enums::EventClass::Disputes,
             None,
@@ -540,6 +558,7 @@ pub async fn disputes_incoming_webhook_flow<W: types::OutgoingWebhookType>(
 async fn bank_transfer_webhook_flow<W: types::OutgoingWebhookType, Ctx: PaymentMethodRetrieve>(
     state: AppState,
     merchant_account: domain::MerchantAccount,
+    business_profile: diesel_models::business_profile::BusinessProfile,
     key_store: domain::MerchantKeyStore,
     webhook_details: api::IncomingWebhookDetails,
     source_verified: bool,
@@ -559,7 +578,14 @@ async fn bank_transfer_webhook_flow<W: types::OutgoingWebhookType, Ctx: PaymentM
             payment_token: payment_attempt.payment_token,
             ..Default::default()
         };
-        payments::payments_core::<api::Authorize, api::PaymentsResponse, _, _, _, Ctx>(
+        Box::pin(payments::payments_core::<
+            api::Authorize,
+            api::PaymentsResponse,
+            _,
+            _,
+            _,
+            Ctx,
+        >(
             state.clone(),
             merchant_account.to_owned(),
             key_store,
@@ -567,8 +593,9 @@ async fn bank_transfer_webhook_flow<W: types::OutgoingWebhookType, Ctx: PaymentM
             request,
             services::api::AuthFlow::Merchant,
             payments::CallConnectorAction::Trigger,
+            None,
             HeaderPayload::default(),
-        )
+        ))
         .await
     } else {
         Err(report!(
@@ -593,6 +620,7 @@ async fn bank_transfer_webhook_flow<W: types::OutgoingWebhookType, Ctx: PaymentM
                 create_event_and_trigger_outgoing_webhook::<W>(
                     state,
                     merchant_account,
+                    business_profile,
                     outgoing_event_type,
                     enums::EventClass::Payments,
                     None,
@@ -617,6 +645,7 @@ async fn bank_transfer_webhook_flow<W: types::OutgoingWebhookType, Ctx: PaymentM
 pub async fn create_event_and_trigger_appropriate_outgoing_webhook(
     state: AppState,
     merchant_account: domain::MerchantAccount,
+    business_profile: diesel_models::business_profile::BusinessProfile,
     event_type: enums::EventType,
     event_class: enums::EventClass,
     intent_reference_id: Option<String>,
@@ -630,6 +659,7 @@ pub async fn create_event_and_trigger_appropriate_outgoing_webhook(
             create_event_and_trigger_outgoing_webhook::<stripe_webhooks::StripeOutgoingWebhook>(
                 state.clone(),
                 merchant_account,
+                business_profile,
                 event_type,
                 event_class,
                 intent_reference_id,
@@ -643,6 +673,7 @@ pub async fn create_event_and_trigger_appropriate_outgoing_webhook(
             create_event_and_trigger_outgoing_webhook::<api_models::webhooks::OutgoingWebhook>(
                 state.clone(),
                 merchant_account,
+                business_profile,
                 event_type,
                 event_class,
                 intent_reference_id,
@@ -660,6 +691,7 @@ pub async fn create_event_and_trigger_appropriate_outgoing_webhook(
 pub async fn create_event_and_trigger_outgoing_webhook<W: types::OutgoingWebhookType>(
     state: AppState,
     merchant_account: domain::MerchantAccount,
+    business_profile: diesel_models::business_profile::BusinessProfile,
     event_type: enums::EventType,
     event_class: enums::EventClass,
     intent_reference_id: Option<String>,
@@ -708,7 +740,7 @@ pub async fn create_event_and_trigger_outgoing_webhook<W: types::OutgoingWebhook
         // may have an actix arbiter
         tokio::spawn(async move {
             let result =
-                trigger_webhook_to_merchant::<W>(merchant_account, outgoing_webhook, &state).await;
+                trigger_webhook_to_merchant::<W>(business_profile, outgoing_webhook, &state).await;
 
             if let Err(e) = result {
                 logger::error!(?e);
@@ -720,11 +752,11 @@ pub async fn create_event_and_trigger_outgoing_webhook<W: types::OutgoingWebhook
 }
 
 pub async fn trigger_webhook_to_merchant<W: types::OutgoingWebhookType>(
-    merchant_account: domain::MerchantAccount,
+    business_profile: diesel_models::business_profile::BusinessProfile,
     webhook: api::OutgoingWebhook,
     state: &AppState,
 ) -> CustomResult<(), errors::WebhooksFlowError> {
-    let webhook_details_json = merchant_account
+    let webhook_details_json = business_profile
         .webhook_details
         .get_required_value("webhook_details")
         .change_context(errors::WebhooksFlowError::MerchantWebhookDetailsNotFound)?;
@@ -745,7 +777,7 @@ pub async fn trigger_webhook_to_merchant<W: types::OutgoingWebhookType>(
     let transformed_outgoing_webhook = W::from(webhook);
 
     let outgoing_webhooks_signature = transformed_outgoing_webhook
-        .get_outgoing_webhooks_signature(merchant_account.payment_response_hash_key.clone())?;
+        .get_outgoing_webhooks_signature(business_profile.payment_response_hash_key.clone())?;
 
     let transformed_outgoing_webhook_string = router_types::RequestBody::log_and_get_request_body(
         &transformed_outgoing_webhook,
@@ -781,7 +813,7 @@ pub async fn trigger_webhook_to_merchant<W: types::OutgoingWebhookType>(
         1,
         &[metrics::KeyValue::new(
             MERCHANT_ID,
-            merchant_account.merchant_id.clone(),
+            business_profile.merchant_id.clone(),
         )],
     );
     logger::debug!(outgoing_webhook_response=?response);
@@ -798,7 +830,7 @@ pub async fn trigger_webhook_to_merchant<W: types::OutgoingWebhookType>(
                     1,
                     &[metrics::KeyValue::new(
                         MERCHANT_ID,
-                        merchant_account.merchant_id.clone(),
+                        business_profile.merchant_id.clone(),
                     )],
                 );
                 let update_event = storage::EventUpdate::UpdateWebhookNotified {
@@ -815,7 +847,7 @@ pub async fn trigger_webhook_to_merchant<W: types::OutgoingWebhookType>(
                     1,
                     &[metrics::KeyValue::new(
                         MERCHANT_ID,
-                        merchant_account.merchant_id.clone(),
+                        business_profile.merchant_id.clone(),
                     )],
                 );
                 // [#217]: Schedule webhook for retry.
@@ -835,14 +867,14 @@ pub async fn webhooks_wrapper<W: types::OutgoingWebhookType, Ctx: PaymentMethodR
     connector_name_or_mca_id: &str,
     body: actix_web::web::Bytes,
 ) -> RouterResponse<serde_json::Value> {
-    let (application_response, _webhooks_response_tracker) = webhooks_core::<W, Ctx>(
+    let (application_response, _webhooks_response_tracker) = Box::pin(webhooks_core::<W, Ctx>(
         state,
         req,
         merchant_account,
         key_store,
         connector_name_or_mca_id,
         body,
-    )
+    ))
     .await?;
 
     Ok(application_response)
@@ -944,8 +976,13 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType, Ctx: PaymentMethodRetr
             return Ok((response, WebhookResponseTracker::NoEffect));
         }
     };
+    logger::info!(event_type=?event_type);
 
-    let process_webhook_further = utils::lookup_webhook_event(
+    let is_webhook_event_supported = !matches!(
+        event_type,
+        api_models::webhooks::IncomingWebhookEvent::EventNotSupported
+    );
+    let is_webhook_event_enabled = !utils::is_webhook_event_disabled(
         &*state.clone().store,
         connector_name.as_str(),
         &merchant_account.merchant_id,
@@ -953,8 +990,10 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType, Ctx: PaymentMethodRetr
     )
     .await;
 
+    //process webhook further only if webhook event is enabled and is not event_not_supported
+    let process_webhook_further = is_webhook_event_enabled && is_webhook_event_supported;
+
     logger::info!(process_webhook=?process_webhook_further);
-    logger::info!(event_type=?event_type);
 
     let flow_type: api::WebhookFlow = event_type.to_owned().into();
     let webhook_effect = if process_webhook_further
@@ -1047,32 +1086,50 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType, Ctx: PaymentMethodRetr
                 )?,
         };
 
+        let profile_id = merchant_connector_account
+            .profile_id
+            .as_ref()
+            .get_required_value("profile_id")
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Could not find profile_id in merchant connector account")?;
+
+        let business_profile = state
+            .store
+            .find_business_profile_by_profile_id(profile_id)
+            .await
+            .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound {
+                id: profile_id.to_string(),
+            })?;
+
         match flow_type {
-            api::WebhookFlow::Payment => payments_incoming_webhook_flow::<W, Ctx>(
+            api::WebhookFlow::Payment => Box::pin(payments_incoming_webhook_flow::<W, Ctx>(
                 state.clone(),
                 merchant_account,
+                business_profile,
                 key_store,
                 webhook_details,
                 source_verified,
-            )
+            ))
             .await
             .attach_printable("Incoming webhook flow for payments failed")?,
 
-            api::WebhookFlow::Refund => refunds_incoming_webhook_flow::<W>(
+            api::WebhookFlow::Refund => Box::pin(refunds_incoming_webhook_flow::<W>(
                 state.clone(),
                 merchant_account,
+                business_profile,
                 key_store,
                 webhook_details,
                 connector_name.as_str(),
                 source_verified,
                 event_type,
-            )
+            ))
             .await
             .attach_printable("Incoming webhook flow for refunds failed")?,
 
             api::WebhookFlow::Dispute => disputes_incoming_webhook_flow::<W>(
                 state.clone(),
                 merchant_account,
+                business_profile,
                 webhook_details,
                 source_verified,
                 *connector,
@@ -1082,13 +1139,14 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType, Ctx: PaymentMethodRetr
             .await
             .attach_printable("Incoming webhook flow for disputes failed")?,
 
-            api::WebhookFlow::BankTransfer => bank_transfer_webhook_flow::<W, Ctx>(
+            api::WebhookFlow::BankTransfer => Box::pin(bank_transfer_webhook_flow::<W, Ctx>(
                 state.clone(),
                 merchant_account,
+                business_profile,
                 key_store,
                 webhook_details,
                 source_verified,
-            )
+            ))
             .await
             .attach_printable("Incoming bank-transfer webhook flow failed")?,
 
@@ -1097,6 +1155,7 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType, Ctx: PaymentMethodRetr
             api::WebhookFlow::Mandate => mandates_incoming_webhook_flow::<W>(
                 state.clone(),
                 merchant_account,
+                business_profile,
                 webhook_details,
                 source_verified,
                 event_type,
@@ -1194,6 +1253,7 @@ async fn fetch_mca_and_connector(
             &state.conf.connectors,
             &mca.connector_name,
             api::GetToken::Connector,
+            Some(mca.merchant_connector_id.clone()),
         )
         .change_context(errors::ApiErrorResponse::InvalidRequestData {
             message: "invalid connector name received".to_string(),
@@ -1202,10 +1262,12 @@ async fn fetch_mca_and_connector(
 
         Ok((mca, connector))
     } else {
+        // Merchant connector account is already being queried, it is safe to set connector id as None
         let connector = api::ConnectorData::get_connector_by_name(
             &state.conf.connectors,
             connector_name_or_mca_id,
             api::GetToken::Connector,
+            None,
         )
         .change_context(errors::ApiErrorResponse::InvalidRequestData {
             message: "invalid connector name received".to_string(),
diff --git a/crates/router/src/core/webhooks/utils.rs b/crates/router/src/core/webhooks/utils.rs
index b187001e10e6..322440e53138 100644
--- a/crates/router/src/core/webhooks/utils.rs
+++ b/crates/router/src/core/webhooks/utils.rs
@@ -9,20 +9,10 @@ use crate::{
         payments::helpers,
     },
     db::{get_and_deserialize_key, StorageInterface},
+    services::logger,
     types::{self, api, domain, PaymentAddress},
 };
 
-fn default_webhook_config() -> api::MerchantWebhookConfig {
-    std::collections::HashSet::from([
-        api::IncomingWebhookEvent::PaymentIntentSuccess,
-        api::IncomingWebhookEvent::PaymentIntentFailure,
-        api::IncomingWebhookEvent::PaymentIntentProcessing,
-        api::IncomingWebhookEvent::PaymentIntentCancelled,
-        api::IncomingWebhookEvent::PaymentActionRequired,
-        api::IncomingWebhookEvent::RefundSuccess,
-    ])
-}
-
 const IRRELEVANT_PAYMENT_ID_IN_SOURCE_VERIFICATION_FLOW: &str =
     "irrelevant_payment_id_in_source_verification_flow";
 const IRRELEVANT_ATTEMPT_ID_IN_SOURCE_VERIFICATION_FLOW: &str =
@@ -30,38 +20,40 @@ const IRRELEVANT_ATTEMPT_ID_IN_SOURCE_VERIFICATION_FLOW: &str =
 const IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_SOURCE_VERIFICATION_FLOW: &str =
     "irrelevant_connector_request_reference_id_in_source_verification_flow";
 
-/// Check whether the merchant has configured to process the webhook `event` for the `connector`
+/// Check whether the merchant has configured to disable the webhook `event` for the `connector`
 /// First check for the key "whconf_{merchant_id}_{connector_id}" in redis,
-/// if not found, fetch from configs table in database, if not found use default
-pub async fn lookup_webhook_event(
+/// if not found, fetch from configs table in database
+pub async fn is_webhook_event_disabled(
     db: &dyn StorageInterface,
     connector_id: &str,
     merchant_id: &str,
     event: &api::IncomingWebhookEvent,
 ) -> bool {
-    let redis_key = format!("whconf_{merchant_id}_{connector_id}");
-    let merchant_webhook_config_result =
-        get_and_deserialize_key(db, &redis_key, "MerchantWebhookConfig")
-            .await
-            .map(|h| &h | &default_webhook_config());
+    let redis_key = format!("whconf_disabled_events_{merchant_id}_{connector_id}");
+    let merchant_webhook_disable_config_result: CustomResult<
+        api::MerchantWebhookConfig,
+        redis_interface::errors::RedisError,
+    > = get_and_deserialize_key(db, &redis_key, "MerchantWebhookConfig").await;
 
-    match merchant_webhook_config_result {
+    match merchant_webhook_disable_config_result {
         Ok(merchant_webhook_config) => merchant_webhook_config.contains(event),
         Err(..) => {
             //if failed to fetch from redis. fetch from db and populate redis
             db.find_config_by_key(&redis_key)
                 .await
                 .map(|config| {
-                    if let Ok(set) =
-                        serde_json::from_str::<api::MerchantWebhookConfig>(&config.config)
-                    {
-                        &set | &default_webhook_config()
-                    } else {
-                        default_webhook_config()
+                    match serde_json::from_str::<api::MerchantWebhookConfig>(&config.config) {
+                        Ok(set) => set.contains(event),
+                        Err(err) => {
+                            logger::warn!(?err, "error while parsing merchant webhook config");
+                            false
+                        }
                     }
                 })
-                .unwrap_or_else(|_| default_webhook_config())
-                .contains(event)
+                .unwrap_or_else(|err| {
+                    logger::warn!(?err, "error while fetching merchant webhook config");
+                    false
+                })
         }
     }
 }
diff --git a/crates/router/src/db.rs b/crates/router/src/db.rs
index 4270d2ab6490..9687f7f97c92 100644
--- a/crates/router/src/db.rs
+++ b/crates/router/src/db.rs
@@ -5,24 +5,28 @@ pub mod cache;
 pub mod capture;
 pub mod cards_info;
 pub mod configs;
-pub mod connector_response;
 pub mod customers;
 pub mod dispute;
 pub mod ephemeral_key;
 pub mod events;
 pub mod file;
 pub mod fraud_check;
+pub mod gsm;
 pub mod locker_mock_up;
 pub mod mandate;
 pub mod merchant_account;
 pub mod merchant_connector_account;
 pub mod merchant_key_store;
+pub mod organization;
 pub mod payment_link;
 pub mod payment_method;
 pub mod payout_attempt;
 pub mod payouts;
 pub mod refund;
 pub mod reverse_lookup;
+pub mod routing_algorithm;
+pub mod user;
+pub mod user_role;
 
 use data_models::payments::{
     payment_attempt::PaymentAttemptInterface, payment_intent::PaymentIntentInterface,
@@ -49,7 +53,6 @@ pub trait StorageInterface:
     + api_keys::ApiKeyInterface
     + configs::ConfigInterface
     + capture::CaptureInterface
-    + connector_response::ConnectorResponseInterface
     + customers::CustomerInterface
     + dispute::DisputeInterface
     + ephemeral_key::EphemeralKeyInterface
@@ -74,7 +77,13 @@ pub trait StorageInterface:
     + MasterKeyInterface
     + payment_link::PaymentLinkInterface
     + RedisConnInterface
+    + RequestIdStore
     + business_profile::BusinessProfileInterface
+    + organization::OrganizationInterface
+    + routing_algorithm::RoutingAlgorithmInterface
+    + gsm::GsmInterface
+    + user::UserInterface
+    + user_role::UserRoleInterface
     + 'static
 {
     fn get_scheduler_db(&self) -> Box<dyn scheduler::SchedulerInterface>;
@@ -114,6 +123,25 @@ impl StorageInterface for MockDb {
     }
 }
 
+pub trait RequestIdStore {
+    fn add_request_id(&mut self, _request_id: String) {}
+    fn get_request_id(&self) -> Option<String> {
+        None
+    }
+}
+
+impl RequestIdStore for MockDb {}
+
+impl RequestIdStore for Store {
+    fn add_request_id(&mut self, request_id: String) {
+        self.request_id = Some(request_id)
+    }
+
+    fn get_request_id(&self) -> Option<String> {
+        self.request_id.clone()
+    }
+}
+
 pub async fn get_and_deserialize_key<T>(
     db: &dyn StorageInterface,
     key: &str,
diff --git a/crates/router/src/db/address.rs b/crates/router/src/db/address.rs
index 20f7bdb9120f..689d1f9c7891 100644
--- a/crates/router/src/db/address.rs
+++ b/crates/router/src/db/address.rs
@@ -339,7 +339,7 @@ mod storage {
                 MerchantStorageScheme::RedisKv => {
                     let key = format!("mid_{}_pid_{}", merchant_id, payment_id);
                     let field = format!("add_{}", address_id);
-                    db_utils::try_redis_get_else_try_database_get(
+                    Box::pin(db_utils::try_redis_get_else_try_database_get(
                         async {
                             kv_wrapper(
                                 self,
@@ -350,7 +350,7 @@ mod storage {
                             .try_into_hget()
                         },
                         database_call,
-                    )
+                    ))
                     .await
                 }
             }?;
@@ -763,7 +763,8 @@ impl AddressInterface for MockDb {
             .await
             .iter_mut()
             .find(|address| {
-                address.customer_id == customer_id && address.merchant_id == merchant_id
+                address.customer_id == Some(customer_id.to_string())
+                    && address.merchant_id == merchant_id
             })
             .map(|a| {
                 let address_updated =
diff --git a/crates/router/src/db/cache.rs b/crates/router/src/db/cache.rs
index 06ab85591a93..0688665f0c4c 100644
--- a/crates/router/src/db/cache.rs
+++ b/crates/router/src/db/cache.rs
@@ -100,9 +100,9 @@ where
     Ok(data)
 }
 
-pub async fn publish_into_redact_channel<'a>(
+pub async fn publish_into_redact_channel<'a, K: IntoIterator<Item = CacheKind<'a>> + Send>(
     store: &dyn StorageInterface,
-    key: CacheKind<'a>,
+    keys: K,
 ) -> CustomResult<usize, errors::StorageError> {
     let redis_conn = store
         .get_redis_conn()
@@ -111,10 +111,18 @@ pub async fn publish_into_redact_channel<'a>(
         ))
         .attach_printable("Failed to get redis connection")?;
 
-    redis_conn
-        .publish(consts::PUB_SUB_CHANNEL, key)
-        .await
-        .change_context(errors::StorageError::KVError)
+    let futures = keys.into_iter().map(|key| async {
+        redis_conn
+            .clone()
+            .publish(consts::PUB_SUB_CHANNEL, key)
+            .await
+            .change_context(errors::StorageError::KVError)
+    });
+
+    Ok(futures::future::try_join_all(futures)
+        .await?
+        .iter()
+        .sum::<usize>())
 }
 
 pub async fn publish_and_redact<'a, T, F, Fut>(
@@ -127,6 +135,21 @@ where
     Fut: futures::Future<Output = CustomResult<T, errors::StorageError>> + Send,
 {
     let data = fun().await?;
-    publish_into_redact_channel(store, key).await?;
+    publish_into_redact_channel(store, [key]).await?;
+    Ok(data)
+}
+
+pub async fn publish_and_redact_multiple<'a, T, F, Fut, K>(
+    store: &dyn StorageInterface,
+    keys: K,
+    fun: F,
+) -> CustomResult<T, errors::StorageError>
+where
+    F: FnOnce() -> Fut + Send,
+    Fut: futures::Future<Output = CustomResult<T, errors::StorageError>> + Send,
+    K: IntoIterator<Item = CacheKind<'a>> + Send,
+{
+    let data = fun().await?;
+    publish_into_redact_channel(store, keys).await?;
     Ok(data)
 }
diff --git a/crates/router/src/db/connector_response.rs b/crates/router/src/db/connector_response.rs
deleted file mode 100644
index 354231d136ec..000000000000
--- a/crates/router/src/db/connector_response.rs
+++ /dev/null
@@ -1,343 +0,0 @@
-use error_stack::{IntoReport, ResultExt};
-use router_env::{instrument, tracing};
-
-use super::{MockDb, Store};
-use crate::{
-    core::errors::{self, CustomResult},
-    types::storage::{self as storage_type, enums},
-};
-
-#[async_trait::async_trait]
-pub trait ConnectorResponseInterface {
-    async fn insert_connector_response(
-        &self,
-        connector_response: storage_type::ConnectorResponseNew,
-        storage_scheme: enums::MerchantStorageScheme,
-    ) -> CustomResult<storage_type::ConnectorResponse, errors::StorageError>;
-
-    async fn find_connector_response_by_payment_id_merchant_id_attempt_id(
-        &self,
-        payment_id: &str,
-        merchant_id: &str,
-        attempt_id: &str,
-        storage_scheme: enums::MerchantStorageScheme,
-    ) -> CustomResult<storage_type::ConnectorResponse, errors::StorageError>;
-
-    async fn update_connector_response(
-        &self,
-        this: storage_type::ConnectorResponse,
-        payment_attempt: storage_type::ConnectorResponseUpdate,
-        storage_scheme: enums::MerchantStorageScheme,
-    ) -> CustomResult<storage_type::ConnectorResponse, errors::StorageError>;
-}
-
-#[cfg(not(feature = "kv_store"))]
-mod storage {
-    use error_stack::IntoReport;
-    use router_env::{instrument, tracing};
-
-    use super::Store;
-    use crate::{
-        connection,
-        core::errors::{self, CustomResult},
-        types::storage::{self as storage_type, enums},
-    };
-
-    #[async_trait::async_trait]
-    impl super::ConnectorResponseInterface for Store {
-        #[instrument(skip_all)]
-        async fn insert_connector_response(
-            &self,
-            connector_response: storage_type::ConnectorResponseNew,
-            _storage_scheme: enums::MerchantStorageScheme,
-        ) -> CustomResult<storage_type::ConnectorResponse, errors::StorageError> {
-            let conn = connection::pg_connection_write(self).await?;
-            connector_response
-                .insert(&conn)
-                .await
-                .map_err(Into::into)
-                .into_report()
-        }
-
-        #[instrument(skip_all)]
-        async fn find_connector_response_by_payment_id_merchant_id_attempt_id(
-            &self,
-            payment_id: &str,
-            merchant_id: &str,
-            attempt_id: &str,
-            _storage_scheme: enums::MerchantStorageScheme,
-        ) -> CustomResult<storage_type::ConnectorResponse, errors::StorageError> {
-            let conn = connection::pg_connection_read(self).await?;
-            storage_type::ConnectorResponse::find_by_payment_id_merchant_id_attempt_id(
-                &conn,
-                payment_id,
-                merchant_id,
-                attempt_id,
-            )
-            .await
-            .map_err(Into::into)
-            .into_report()
-        }
-
-        async fn update_connector_response(
-            &self,
-            this: storage_type::ConnectorResponse,
-            connector_response_update: storage_type::ConnectorResponseUpdate,
-            _storage_scheme: enums::MerchantStorageScheme,
-        ) -> CustomResult<storage_type::ConnectorResponse, errors::StorageError> {
-            let conn = connection::pg_connection_write(self).await?;
-            this.update(&conn, connector_response_update)
-                .await
-                .map_err(Into::into)
-                .into_report()
-        }
-    }
-}
-
-#[cfg(feature = "kv_store")]
-mod storage {
-
-    use diesel_models::enums as storage_enums;
-    use error_stack::{IntoReport, ResultExt};
-    use redis_interface::HsetnxReply;
-    use router_env::{instrument, tracing};
-    use storage_impl::redis::kv_store::{kv_wrapper, KvOperation};
-
-    use super::Store;
-    use crate::{
-        connection,
-        core::errors::{self, CustomResult},
-        types::storage::{self as storage_type, enums, kv},
-        utils::db_utils,
-    };
-
-    #[async_trait::async_trait]
-    impl super::ConnectorResponseInterface for Store {
-        #[instrument(skip_all)]
-        async fn insert_connector_response(
-            &self,
-            connector_response: storage_type::ConnectorResponseNew,
-            storage_scheme: enums::MerchantStorageScheme,
-        ) -> CustomResult<storage_type::ConnectorResponse, errors::StorageError> {
-            let conn = connection::pg_connection_write(self).await?;
-
-            match storage_scheme {
-                storage_enums::MerchantStorageScheme::PostgresOnly => connector_response
-                    .insert(&conn)
-                    .await
-                    .map_err(Into::into)
-                    .into_report(),
-                storage_enums::MerchantStorageScheme::RedisKv => {
-                    let merchant_id = &connector_response.merchant_id;
-                    let payment_id = &connector_response.payment_id;
-                    let attempt_id = &connector_response.attempt_id;
-
-                    let key = format!("mid_{merchant_id}_pid_{payment_id}");
-                    let field = format!("connector_resp_{merchant_id}_{payment_id}_{attempt_id}");
-
-                    let created_connector_resp = storage_type::ConnectorResponse {
-                        id: Default::default(),
-                        payment_id: connector_response.payment_id.clone(),
-                        merchant_id: connector_response.merchant_id.clone(),
-                        attempt_id: connector_response.attempt_id.clone(),
-                        created_at: connector_response.created_at,
-                        modified_at: connector_response.modified_at,
-                        connector_name: connector_response.connector_name.clone(),
-                        connector_transaction_id: connector_response
-                            .connector_transaction_id
-                            .clone(),
-                        authentication_data: connector_response.authentication_data.clone(),
-                        encoded_data: connector_response.encoded_data.clone(),
-                        updated_by: storage_scheme.to_string(),
-                    };
-
-                    let redis_entry = kv::TypedSql {
-                        op: kv::DBOperation::Insert {
-                            insertable: kv::Insertable::ConnectorResponse(
-                                connector_response.clone(),
-                            ),
-                        },
-                    };
-
-                    match kv_wrapper::<storage_type::ConnectorResponse, _, _>(
-                        self,
-                        KvOperation::HSetNx(&field, &created_connector_resp, redis_entry),
-                        &key,
-                    )
-                    .await
-                    .change_context(errors::StorageError::KVError)?
-                    .try_into_hsetnx()
-                    {
-                        Ok(HsetnxReply::KeyNotSet) => Err(errors::StorageError::DuplicateValue {
-                            entity: "address",
-                            key: Some(key),
-                        })
-                        .into_report(),
-                        Ok(HsetnxReply::KeySet) => Ok(created_connector_resp),
-                        Err(er) => Err(er).change_context(errors::StorageError::KVError),
-                    }
-                }
-            }
-        }
-
-        #[instrument(skip_all)]
-        async fn find_connector_response_by_payment_id_merchant_id_attempt_id(
-            &self,
-            payment_id: &str,
-            merchant_id: &str,
-            attempt_id: &str,
-            storage_scheme: enums::MerchantStorageScheme,
-        ) -> CustomResult<storage_type::ConnectorResponse, errors::StorageError> {
-            let conn = connection::pg_connection_read(self).await?;
-            let database_call = || async {
-                storage_type::ConnectorResponse::find_by_payment_id_merchant_id_attempt_id(
-                    &conn,
-                    payment_id,
-                    merchant_id,
-                    attempt_id,
-                )
-                .await
-                .map_err(Into::into)
-                .into_report()
-            };
-            match storage_scheme {
-                storage_enums::MerchantStorageScheme::PostgresOnly => database_call().await,
-                storage_enums::MerchantStorageScheme::RedisKv => {
-                    let key = format!("mid_{merchant_id}_pid_{payment_id}");
-                    let field = format!("connector_resp_{merchant_id}_{payment_id}_{attempt_id}");
-
-                    db_utils::try_redis_get_else_try_database_get(
-                        async {
-                            kv_wrapper(
-                                self,
-                                KvOperation::<diesel_models::Address>::HGet(&field),
-                                key,
-                            )
-                            .await?
-                            .try_into_hget()
-                        },
-                        database_call,
-                    )
-                    .await
-                }
-            }
-        }
-
-        async fn update_connector_response(
-            &self,
-            this: storage_type::ConnectorResponse,
-            connector_response_update: storage_type::ConnectorResponseUpdate,
-            storage_scheme: enums::MerchantStorageScheme,
-        ) -> CustomResult<storage_type::ConnectorResponse, errors::StorageError> {
-            let conn = connection::pg_connection_write(self).await?;
-            match storage_scheme {
-                storage_enums::MerchantStorageScheme::PostgresOnly => this
-                    .update(&conn, connector_response_update)
-                    .await
-                    .map_err(Into::into)
-                    .into_report(),
-                storage_enums::MerchantStorageScheme::RedisKv => {
-                    let key = format!("mid_{}_pid_{}", this.merchant_id, this.payment_id);
-                    let updated_connector_response = connector_response_update
-                        .clone()
-                        .apply_changeset(this.clone());
-                    let redis_value = serde_json::to_string(&updated_connector_response)
-                        .into_report()
-                        .change_context(errors::StorageError::KVError)?;
-                    let field = format!(
-                        "connector_resp_{}_{}_{}",
-                        &updated_connector_response.merchant_id,
-                        &updated_connector_response.payment_id,
-                        &updated_connector_response.attempt_id
-                    );
-
-                    let redis_entry = kv::TypedSql {
-                        op: kv::DBOperation::Update {
-                            updatable: kv::Updateable::ConnectorResponseUpdate(
-                                kv::ConnectorResponseUpdateMems {
-                                    orig: this,
-                                    update_data: connector_response_update,
-                                },
-                            ),
-                        },
-                    };
-
-                    kv_wrapper::<(), _, _>(
-                        self,
-                        KvOperation::Hset::<storage_type::ConnectorResponse>(
-                            (&field, redis_value),
-                            redis_entry,
-                        ),
-                        &key,
-                    )
-                    .await
-                    .change_context(errors::StorageError::KVError)?
-                    .try_into_hset()
-                    .change_context(errors::StorageError::KVError)?;
-
-                    Ok(updated_connector_response)
-                }
-            }
-        }
-    }
-}
-
-#[async_trait::async_trait]
-impl ConnectorResponseInterface for MockDb {
-    #[instrument(skip_all)]
-    async fn insert_connector_response(
-        &self,
-        new: storage_type::ConnectorResponseNew,
-        storage_scheme: enums::MerchantStorageScheme,
-    ) -> CustomResult<storage_type::ConnectorResponse, errors::StorageError> {
-        let mut connector_response = self.connector_response.lock().await;
-        let response = storage_type::ConnectorResponse {
-            id: connector_response
-                .len()
-                .try_into()
-                .into_report()
-                .change_context(errors::StorageError::MockDbError)?,
-            payment_id: new.payment_id,
-            merchant_id: new.merchant_id,
-            attempt_id: new.attempt_id,
-            created_at: new.created_at,
-            modified_at: new.modified_at,
-            connector_name: new.connector_name,
-            connector_transaction_id: new.connector_transaction_id,
-            authentication_data: new.authentication_data,
-            encoded_data: new.encoded_data,
-            updated_by: storage_scheme.to_string(),
-        };
-        connector_response.push(response.clone());
-        Ok(response)
-    }
-
-    #[instrument(skip_all)]
-    async fn find_connector_response_by_payment_id_merchant_id_attempt_id(
-        &self,
-        _payment_id: &str,
-        _merchant_id: &str,
-        _attempt_id: &str,
-        _storage_scheme: enums::MerchantStorageScheme,
-    ) -> CustomResult<storage_type::ConnectorResponse, errors::StorageError> {
-        // [#172]: Implement function for `MockDb`
-        Err(errors::StorageError::MockDbError)?
-    }
-
-    // safety: interface only used for testing
-    #[allow(clippy::unwrap_used)]
-    async fn update_connector_response(
-        &self,
-        this: storage_type::ConnectorResponse,
-        connector_response_update: storage_type::ConnectorResponseUpdate,
-        _storage_scheme: enums::MerchantStorageScheme,
-    ) -> CustomResult<storage_type::ConnectorResponse, errors::StorageError> {
-        let mut connector_response = self.connector_response.lock().await;
-        let response = connector_response
-            .iter_mut()
-            .find(|item| item.id == this.id)
-            .unwrap();
-        *response = connector_response_update.apply_changeset(response.clone());
-        Ok(response.clone())
-    }
-}
diff --git a/crates/router/src/db/dispute.rs b/crates/router/src/db/dispute.rs
index 42fb85ad16d5..c63585205bb3 100644
--- a/crates/router/src/db/dispute.rs
+++ b/crates/router/src/db/dispute.rs
@@ -172,6 +172,7 @@ impl DisputeInterface for MockDb {
             connector: dispute.connector,
             profile_id: dispute.profile_id,
             evidence,
+            merchant_connector_id: dispute.merchant_connector_id,
         };
 
         locked_disputes.push(new_dispute.clone());
@@ -405,6 +406,7 @@ mod tests {
                 connector: "connector".into(),
                 evidence: Some(Secret::from(Value::String("evidence".into()))),
                 profile_id: None,
+                merchant_connector_id: None,
             }
         }
 
diff --git a/crates/router/src/db/gsm.rs b/crates/router/src/db/gsm.rs
new file mode 100644
index 000000000000..b623bdc2bcf5
--- /dev/null
+++ b/crates/router/src/db/gsm.rs
@@ -0,0 +1,180 @@
+use diesel_models::gsm as storage;
+use error_stack::IntoReport;
+
+use super::MockDb;
+use crate::{
+    connection,
+    core::errors::{self, CustomResult},
+    services::Store,
+};
+
+#[async_trait::async_trait]
+pub trait GsmInterface {
+    async fn add_gsm_rule(
+        &self,
+        rule: storage::GatewayStatusMappingNew,
+    ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError>;
+    async fn find_gsm_decision(
+        &self,
+        connector: String,
+        flow: String,
+        sub_flow: String,
+        code: String,
+        message: String,
+    ) -> CustomResult<String, errors::StorageError>;
+    async fn find_gsm_rule(
+        &self,
+        connector: String,
+        flow: String,
+        sub_flow: String,
+        code: String,
+        message: String,
+    ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError>;
+    async fn update_gsm_rule(
+        &self,
+        connector: String,
+        flow: String,
+        sub_flow: String,
+        code: String,
+        message: String,
+        data: storage::GatewayStatusMappingUpdate,
+    ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError>;
+
+    async fn delete_gsm_rule(
+        &self,
+        connector: String,
+        flow: String,
+        sub_flow: String,
+        code: String,
+        message: String,
+    ) -> CustomResult<bool, errors::StorageError>;
+}
+
+#[async_trait::async_trait]
+impl GsmInterface for Store {
+    async fn add_gsm_rule(
+        &self,
+        rule: storage::GatewayStatusMappingNew,
+    ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        rule.insert(&conn).await.map_err(Into::into).into_report()
+    }
+
+    async fn find_gsm_decision(
+        &self,
+        connector: String,
+        flow: String,
+        sub_flow: String,
+        code: String,
+        message: String,
+    ) -> CustomResult<String, errors::StorageError> {
+        let conn = connection::pg_connection_read(self).await?;
+        storage::GatewayStatusMap::retrieve_decision(
+            &conn, connector, flow, sub_flow, code, message,
+        )
+        .await
+        .map_err(Into::into)
+        .into_report()
+    }
+
+    async fn find_gsm_rule(
+        &self,
+        connector: String,
+        flow: String,
+        sub_flow: String,
+        code: String,
+        message: String,
+    ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError> {
+        let conn = connection::pg_connection_read(self).await?;
+        storage::GatewayStatusMap::find(&conn, connector, flow, sub_flow, code, message)
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+
+    async fn update_gsm_rule(
+        &self,
+        connector: String,
+        flow: String,
+        sub_flow: String,
+        code: String,
+        message: String,
+        data: storage::GatewayStatusMappingUpdate,
+    ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        storage::GatewayStatusMap::update(&conn, connector, flow, sub_flow, code, message, data)
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+
+    async fn delete_gsm_rule(
+        &self,
+        connector: String,
+        flow: String,
+        sub_flow: String,
+        code: String,
+        message: String,
+    ) -> CustomResult<bool, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        storage::GatewayStatusMap::delete(&conn, connector, flow, sub_flow, code, message)
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+}
+
+#[async_trait::async_trait]
+impl GsmInterface for MockDb {
+    async fn add_gsm_rule(
+        &self,
+        _rule: storage::GatewayStatusMappingNew,
+    ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError> {
+        Err(errors::StorageError::MockDbError)?
+    }
+
+    async fn find_gsm_decision(
+        &self,
+        _connector: String,
+        _flow: String,
+        _sub_flow: String,
+        _code: String,
+        _message: String,
+    ) -> CustomResult<String, errors::StorageError> {
+        Err(errors::StorageError::MockDbError)?
+    }
+
+    async fn find_gsm_rule(
+        &self,
+        _connector: String,
+        _flow: String,
+        _sub_flow: String,
+        _code: String,
+        _message: String,
+    ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError> {
+        Err(errors::StorageError::MockDbError)?
+    }
+
+    async fn update_gsm_rule(
+        &self,
+        _connector: String,
+        _flow: String,
+        _sub_flow: String,
+        _code: String,
+        _message: String,
+        _data: storage::GatewayStatusMappingUpdate,
+    ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError> {
+        Err(errors::StorageError::MockDbError)?
+    }
+
+    async fn delete_gsm_rule(
+        &self,
+        _connector: String,
+        _flow: String,
+        _sub_flow: String,
+        _code: String,
+        _message: String,
+    ) -> CustomResult<bool, errors::StorageError> {
+        Err(errors::StorageError::MockDbError)?
+    }
+}
diff --git a/crates/router/src/db/mandate.rs b/crates/router/src/db/mandate.rs
index 381eecbe7b21..fcd71719657b 100644
--- a/crates/router/src/db/mandate.rs
+++ b/crates/router/src/db/mandate.rs
@@ -290,6 +290,7 @@ impl MandateInterface for MockDb {
             end_date: mandate_new.end_date,
             metadata: mandate_new.metadata,
             connector_mandate_ids: mandate_new.connector_mandate_ids,
+            merchant_connector_id: mandate_new.merchant_connector_id,
         };
         mandates.push(mandate.clone());
         Ok(mandate)
diff --git a/crates/router/src/db/merchant_account.rs b/crates/router/src/db/merchant_account.rs
index e0bff7d9069c..0d3ce99b948d 100644
--- a/crates/router/src/db/merchant_account.rs
+++ b/crates/router/src/db/merchant_account.rs
@@ -399,19 +399,17 @@ async fn publish_and_redact_merchant_account_cache(
     store: &dyn super::StorageInterface,
     merchant_account: &storage::MerchantAccount,
 ) -> CustomResult<(), errors::StorageError> {
-    super::cache::publish_into_redact_channel(
-        store,
-        CacheKind::Accounts(merchant_account.merchant_id.as_str().into()),
-    )
-    .await?;
-    merchant_account
+    let publishable_key = merchant_account
         .publishable_key
         .as_ref()
-        .async_map(|pub_key| async {
-            super::cache::publish_into_redact_channel(store, CacheKind::Accounts(pub_key.into()))
-                .await
-        })
-        .await
-        .transpose()?;
+        .map(|publishable_key| CacheKind::Accounts(publishable_key.into()));
+
+    let mut cache_keys = vec![CacheKind::Accounts(
+        merchant_account.merchant_id.as_str().into(),
+    )];
+
+    cache_keys.extend(publishable_key.into_iter());
+
+    super::cache::publish_into_redact_channel(store, cache_keys).await?;
     Ok(())
 }
diff --git a/crates/router/src/db/merchant_connector_account.rs b/crates/router/src/db/merchant_connector_account.rs
index 491e5b788103..ecf52531f28a 100644
--- a/crates/router/src/db/merchant_connector_account.rs
+++ b/crates/router/src/db/merchant_connector_account.rs
@@ -1,7 +1,4 @@
-use std::cmp::Ordering;
-
 use common_utils::ext_traits::{AsyncExt, ByteSliceExt, Encode};
-use diesel_models::errors as storage_errors;
 use error_stack::{IntoReport, ResultExt};
 #[cfg(feature = "accounts_cache")]
 use storage_impl::redis::cache;
@@ -130,7 +127,7 @@ where
         merchant_id: &str,
         connector_name: &str,
         key_store: &domain::MerchantKeyStore,
-    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError>;
+    ) -> CustomResult<Vec<domain::MerchantConnectorAccount>, errors::StorageError>;
 
     async fn insert_merchant_connector_account(
         &self,
@@ -263,69 +260,70 @@ impl MerchantConnectorAccountInterface for Store {
         merchant_id: &str,
         connector_name: &str,
         key_store: &domain::MerchantKeyStore,
+    ) -> CustomResult<Vec<domain::MerchantConnectorAccount>, errors::StorageError> {
+        let conn = connection::pg_connection_read(self).await?;
+        storage::MerchantConnectorAccount::find_by_merchant_id_connector_name(
+            &conn,
+            merchant_id,
+            connector_name,
+        )
+        .await
+        .map_err(Into::into)
+        .into_report()
+        .async_and_then(|items| async {
+            let mut output = Vec::with_capacity(items.len());
+            for item in items.into_iter() {
+                output.push(
+                    item.convert(key_store.key.get_inner())
+                        .await
+                        .change_context(errors::StorageError::DecryptionError)?,
+                )
+            }
+            Ok(output)
+        })
+        .await
+    }
+
+    async fn find_by_merchant_connector_account_merchant_id_merchant_connector_id(
+        &self,
+        merchant_id: &str,
+        merchant_connector_id: &str,
+        key_store: &domain::MerchantKeyStore,
     ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
         let find_call = || async {
             let conn = connection::pg_connection_read(self).await?;
-            storage::MerchantConnectorAccount::find_by_merchant_id_connector_name(
+            storage::MerchantConnectorAccount::find_by_merchant_id_merchant_connector_id(
                 &conn,
                 merchant_id,
-                connector_name,
+                merchant_connector_id,
             )
             .await
             .map_err(Into::into)
             .into_report()
         };
-        let mca_list = find_call().await?;
-        match mca_list.len().cmp(&1) {
-            Ordering::Less => {
-                Err(errors::StorageError::ValueNotFound("MerchantConnectorAccount".into()).into())
-                    .attach_printable(format!(
-                        "No records found for {} and {}",
-                        merchant_id, connector_name
-                    ))
-            }
-            Ordering::Greater => Err(errors::StorageError::DatabaseError(
-                storage_errors::DatabaseError::Others.into(),
-            ))
-            .into_report()
-            .attach_printable(format!(
-                "Found multiple records for {} and {}",
-                merchant_id, connector_name
-            )),
-            Ordering::Equal => match mca_list.first() {
-                Some(mca) => mca
-                    .to_owned()
-                    .convert(key_store.key.get_inner())
-                    .await
-                    .change_context(errors::StorageError::DeserializationFailed),
-                None => Err(
-                    errors::StorageError::ValueNotFound("MerchantConnectorAccount".into()).into(),
-                ),
-            },
-        }
-    }
 
-    async fn find_by_merchant_connector_account_merchant_id_merchant_connector_id(
-        &self,
-        merchant_id: &str,
-        merchant_connector_id: &str,
-        key_store: &domain::MerchantKeyStore,
-    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
-        let conn = connection::pg_connection_read(self).await?;
-        storage::MerchantConnectorAccount::find_by_merchant_id_merchant_connector_id(
-            &conn,
-            merchant_id,
-            merchant_connector_id,
-        )
-        .await
-        .map_err(Into::into)
-        .into_report()
-        .async_and_then(|item| async {
-            item.convert(key_store.key.get_inner())
+        #[cfg(not(feature = "accounts_cache"))]
+        {
+            find_call()
+                .await?
+                .convert(key_store.key.get_inner())
                 .await
                 .change_context(errors::StorageError::DecryptionError)
-        })
-        .await
+        }
+
+        #[cfg(feature = "accounts_cache")]
+        {
+            super::cache::get_or_populate_in_memory(
+                self,
+                &format!("{}_{}", merchant_id, merchant_connector_id),
+                find_call,
+                &cache::ACCOUNTS_CACHE,
+            )
+            .await?
+            .convert(key_store.key.get_inner())
+            .await
+            .change_context(errors::StorageError::DecryptionError)
+        }
     }
 
     async fn insert_merchant_connector_account(
@@ -388,6 +386,9 @@ impl MerchantConnectorAccountInterface for Store {
                 "profile_id".to_string(),
             ))?;
 
+        let _merchant_id = this.merchant_id.clone();
+        let _merchant_connector_id = this.merchant_connector_id.clone();
+
         let update_call = || async {
             let conn = connection::pg_connection_write(self).await?;
             Conversion::convert(this)
@@ -407,9 +408,17 @@ impl MerchantConnectorAccountInterface for Store {
 
         #[cfg(feature = "accounts_cache")]
         {
-            super::cache::publish_and_redact(
+            // Redact both the caches as any one or both might be used because of backwards compatibility
+            super::cache::publish_and_redact_multiple(
                 self,
-                cache::CacheKind::Accounts(format!("{}_{}", _profile_id, _connector_name).into()),
+                [
+                    cache::CacheKind::Accounts(
+                        format!("{}_{}", _profile_id, _connector_name).into(),
+                    ),
+                    cache::CacheKind::Accounts(
+                        format!("{}_{}", _merchant_id, _merchant_connector_id).into(),
+                    ),
+                ],
                 update_call,
             )
             .await
@@ -514,8 +523,8 @@ impl MerchantConnectorAccountInterface for MockDb {
         merchant_id: &str,
         connector_name: &str,
         key_store: &domain::MerchantKeyStore,
-    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
-        let mca_list = self
+    ) -> CustomResult<Vec<domain::MerchantConnectorAccount>, errors::StorageError> {
+        let accounts = self
             .merchant_connector_accounts
             .lock()
             .await
@@ -525,33 +534,16 @@ impl MerchantConnectorAccountInterface for MockDb {
             })
             .cloned()
             .collect::<Vec<_>>();
-        match mca_list.len().cmp(&1) {
-            Ordering::Less => {
-                Err(errors::StorageError::ValueNotFound("MerchantConnectorAccount".into()).into())
-                    .attach_printable(format!(
-                        "No records found for {} and {}",
-                        merchant_id, connector_name
-                    ))
-            }
-            Ordering::Greater => Err(errors::StorageError::DatabaseError(
-                storage_errors::DatabaseError::Others.into(),
-            ))
-            .into_report()
-            .attach_printable(format!(
-                "Found multiple records for {} and {}",
-                merchant_id, connector_name
-            )),
-            Ordering::Equal => match mca_list.first() {
-                Some(mca) => mca
-                    .to_owned()
+        let mut output = Vec::with_capacity(accounts.len());
+        for account in accounts.into_iter() {
+            output.push(
+                account
                     .convert(key_store.key.get_inner())
                     .await
-                    .change_context(errors::StorageError::DeserializationFailed),
-                None => Err(
-                    errors::StorageError::ValueNotFound("MerchantConnectorAccount".into()).into(),
-                ),
-            },
+                    .change_context(errors::StorageError::DecryptionError)?,
+            )
         }
+        Ok(output)
     }
 
     async fn find_merchant_connector_account_by_profile_id_connector_name(
diff --git a/crates/router/src/db/organization.rs b/crates/router/src/db/organization.rs
new file mode 100644
index 000000000000..ddb8d9f9d907
--- /dev/null
+++ b/crates/router/src/db/organization.rs
@@ -0,0 +1,131 @@
+use common_utils::errors::CustomResult;
+use diesel_models::organization as storage;
+use error_stack::IntoReport;
+
+use crate::{connection, core::errors, services::Store};
+
+#[async_trait::async_trait]
+pub trait OrganizationInterface {
+    async fn insert_organization(
+        &self,
+        organization: storage::OrganizationNew,
+    ) -> CustomResult<storage::Organization, errors::StorageError>;
+
+    async fn find_organization_by_org_id(
+        &self,
+        org_id: &str,
+    ) -> CustomResult<storage::Organization, errors::StorageError>;
+
+    async fn update_organization_by_org_id(
+        &self,
+        user_id: &str,
+        update: storage::OrganizationUpdate,
+    ) -> CustomResult<storage::Organization, errors::StorageError>;
+}
+
+#[async_trait::async_trait]
+impl OrganizationInterface for Store {
+    async fn insert_organization(
+        &self,
+        organization: storage::OrganizationNew,
+    ) -> CustomResult<storage::Organization, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        organization
+            .insert(&conn)
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+
+    async fn find_organization_by_org_id(
+        &self,
+        org_id: &str,
+    ) -> CustomResult<storage::Organization, errors::StorageError> {
+        let conn = connection::pg_connection_read(self).await?;
+        storage::Organization::find_by_org_id(&conn, org_id.to_string())
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+
+    async fn update_organization_by_org_id(
+        &self,
+        org_id: &str,
+        update: storage::OrganizationUpdate,
+    ) -> CustomResult<storage::Organization, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+
+        storage::Organization::update_by_org_id(&conn, org_id.to_string(), update)
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+}
+
+#[async_trait::async_trait]
+impl OrganizationInterface for super::MockDb {
+    async fn insert_organization(
+        &self,
+        organization: storage::OrganizationNew,
+    ) -> CustomResult<storage::Organization, errors::StorageError> {
+        let mut organizations = self.organizations.lock().await;
+
+        if organizations
+            .iter()
+            .any(|org| org.org_id == organization.org_id)
+        {
+            Err(errors::StorageError::DuplicateValue {
+                entity: "org_id",
+                key: None,
+            })?
+        }
+        let org = storage::Organization {
+            org_id: organization.org_id.clone(),
+            org_name: organization.org_name,
+        };
+        organizations.push(org.clone());
+        Ok(org)
+    }
+
+    async fn find_organization_by_org_id(
+        &self,
+        org_id: &str,
+    ) -> CustomResult<storage::Organization, errors::StorageError> {
+        let organizations = self.organizations.lock().await;
+
+        organizations
+            .iter()
+            .find(|org| org.org_id == org_id)
+            .cloned()
+            .ok_or(
+                errors::StorageError::ValueNotFound(format!(
+                    "No organization available for org_id = {org_id}"
+                ))
+                .into(),
+            )
+    }
+
+    async fn update_organization_by_org_id(
+        &self,
+        org_id: &str,
+        update: storage::OrganizationUpdate,
+    ) -> CustomResult<storage::Organization, errors::StorageError> {
+        let mut organizations = self.organizations.lock().await;
+
+        organizations
+            .iter_mut()
+            .find(|org| org.org_id == org_id)
+            .map(|org| match &update {
+                storage::OrganizationUpdate::Update { org_name } => storage::Organization {
+                    org_name: org_name.clone(),
+                    ..org.to_owned()
+                },
+            })
+            .ok_or(
+                errors::StorageError::ValueNotFound(format!(
+                    "No organization available for org_id = {org_id}"
+                ))
+                .into(),
+            )
+    }
+}
diff --git a/crates/router/src/db/refund.rs b/crates/router/src/db/refund.rs
index ae586a48adda..8ac8bd106eff 100644
--- a/crates/router/src/db/refund.rs
+++ b/crates/router/src/db/refund.rs
@@ -78,7 +78,7 @@ pub trait RefundInterface {
     async fn filter_refund_by_meta_constraints(
         &self,
         merchant_id: &str,
-        refund_details: &api_models::refunds::TimeRange,
+        refund_details: &api_models::payments::TimeRange,
         storage_scheme: enums::MerchantStorageScheme,
     ) -> CustomResult<api_models::refunds::RefundListMetaData, errors::StorageError>;
 
@@ -232,7 +232,7 @@ mod storage {
         async fn filter_refund_by_meta_constraints(
             &self,
             merchant_id: &str,
-            refund_details: &api_models::refunds::TimeRange,
+            refund_details: &api_models::payments::TimeRange,
             _storage_scheme: enums::MerchantStorageScheme,
         ) -> CustomResult<api_models::refunds::RefundListMetaData, errors::StorageError> {
             let conn = connection::pg_connection_read(self).await?;
@@ -310,7 +310,7 @@ mod storage {
                         .await?;
 
                     let key = &lookup.pk_id;
-                    db_utils::try_redis_get_else_try_database_get(
+                    Box::pin(db_utils::try_redis_get_else_try_database_get(
                         async {
                             kv_wrapper(
                                 self,
@@ -321,7 +321,7 @@ mod storage {
                             .try_into_hget()
                         },
                         database_call,
-                    )
+                    ))
                     .await
                 }
             }
@@ -368,6 +368,7 @@ mod storage {
                         refund_reason: new.refund_reason.clone(),
                         profile_id: new.profile_id.clone(),
                         updated_by: new.updated_by.clone(),
+                        merchant_connector_id: new.merchant_connector_id.clone(),
                     };
 
                     let field = format!(
@@ -489,7 +490,7 @@ mod storage {
 
                     let pattern = db_utils::generate_hscan_pattern_for_refund(&lookup.sk_id);
 
-                    db_utils::try_redis_get_else_try_database_get(
+                    Box::pin(db_utils::try_redis_get_else_try_database_get(
                         async {
                             kv_wrapper(
                                 self,
@@ -500,7 +501,7 @@ mod storage {
                             .try_into_scan()
                         },
                         database_call,
-                    )
+                    ))
                     .await
                 }
             }
@@ -580,7 +581,7 @@ mod storage {
                         .await?;
 
                     let key = &lookup.pk_id;
-                    db_utils::try_redis_get_else_try_database_get(
+                    Box::pin(db_utils::try_redis_get_else_try_database_get(
                         async {
                             kv_wrapper(
                                 self,
@@ -591,7 +592,7 @@ mod storage {
                             .try_into_hget()
                         },
                         database_call,
-                    )
+                    ))
                     .await
                 }
             }
@@ -625,7 +626,7 @@ mod storage {
                         .await?;
 
                     let key = &lookup.pk_id;
-                    db_utils::try_redis_get_else_try_database_get(
+                    Box::pin(db_utils::try_redis_get_else_try_database_get(
                         async {
                             kv_wrapper(
                                 self,
@@ -636,7 +637,7 @@ mod storage {
                             .try_into_hget()
                         },
                         database_call,
-                    )
+                    ))
                     .await
                 }
             }
@@ -663,7 +664,7 @@ mod storage {
                 enums::MerchantStorageScheme::PostgresOnly => database_call().await,
                 enums::MerchantStorageScheme::RedisKv => {
                     let key = format!("mid_{merchant_id}_pid_{payment_id}");
-                    db_utils::try_redis_get_else_try_database_get(
+                    Box::pin(db_utils::try_redis_get_else_try_database_get(
                         async {
                             kv_wrapper(
                                 self,
@@ -674,7 +675,7 @@ mod storage {
                             .try_into_scan()
                         },
                         database_call,
-                    )
+                    ))
                     .await
                 }
             }
@@ -706,7 +707,7 @@ mod storage {
         async fn filter_refund_by_meta_constraints(
             &self,
             merchant_id: &str,
-            refund_details: &api_models::refunds::TimeRange,
+            refund_details: &api_models::payments::TimeRange,
             _storage_scheme: enums::MerchantStorageScheme,
         ) -> CustomResult<api_models::refunds::RefundListMetaData, errors::StorageError> {
             let conn = connection::pg_connection_read(self).await?;
@@ -796,6 +797,7 @@ impl RefundInterface for MockDb {
             refund_reason: new.refund_reason.clone(),
             profile_id: new.profile_id,
             updated_by: new.updated_by,
+            merchant_connector_id: new.merchant_connector_id,
         };
         refunds.push(refund.clone());
         Ok(refund)
@@ -977,7 +979,7 @@ impl RefundInterface for MockDb {
     async fn filter_refund_by_meta_constraints(
         &self,
         _merchant_id: &str,
-        refund_details: &api_models::refunds::TimeRange,
+        refund_details: &api_models::payments::TimeRange,
         _storage_scheme: enums::MerchantStorageScheme,
     ) -> CustomResult<api_models::refunds::RefundListMetaData, errors::StorageError> {
         let refunds = self.refunds.lock().await;
diff --git a/crates/router/src/db/reverse_lookup.rs b/crates/router/src/db/reverse_lookup.rs
index 4a4056032b18..445e171fa277 100644
--- a/crates/router/src/db/reverse_lookup.rs
+++ b/crates/router/src/db/reverse_lookup.rs
@@ -150,7 +150,11 @@ mod storage {
                         .try_into_get()
                     };
 
-                    db_utils::try_redis_get_else_try_database_get(redis_fut, database_call).await
+                    Box::pin(db_utils::try_redis_get_else_try_database_get(
+                        redis_fut,
+                        database_call,
+                    ))
+                    .await
                 }
             }
         }
diff --git a/crates/router/src/db/routing_algorithm.rs b/crates/router/src/db/routing_algorithm.rs
new file mode 100644
index 000000000000..58550b2f01fa
--- /dev/null
+++ b/crates/router/src/db/routing_algorithm.rs
@@ -0,0 +1,199 @@
+use diesel_models::routing_algorithm as routing_storage;
+use error_stack::IntoReport;
+use storage_impl::mock_db::MockDb;
+
+use crate::{
+    connection,
+    core::errors::{self, CustomResult},
+    services::Store,
+};
+
+type StorageResult<T> = CustomResult<T, errors::StorageError>;
+
+#[async_trait::async_trait]
+pub trait RoutingAlgorithmInterface {
+    async fn insert_routing_algorithm(
+        &self,
+        routing_algorithm: routing_storage::RoutingAlgorithm,
+    ) -> StorageResult<routing_storage::RoutingAlgorithm>;
+
+    async fn find_routing_algorithm_by_profile_id_algorithm_id(
+        &self,
+        profile_id: &str,
+        algorithm_id: &str,
+    ) -> StorageResult<routing_storage::RoutingAlgorithm>;
+
+    async fn find_routing_algorithm_by_algorithm_id_merchant_id(
+        &self,
+        algorithm_id: &str,
+        merchant_id: &str,
+    ) -> StorageResult<routing_storage::RoutingAlgorithm>;
+
+    async fn find_routing_algorithm_metadata_by_algorithm_id_profile_id(
+        &self,
+        algorithm_id: &str,
+        profile_id: &str,
+    ) -> StorageResult<routing_storage::RoutingProfileMetadata>;
+
+    async fn list_routing_algorithm_metadata_by_profile_id(
+        &self,
+        profile_id: &str,
+        limit: i64,
+        offset: i64,
+    ) -> StorageResult<Vec<routing_storage::RoutingAlgorithmMetadata>>;
+
+    async fn list_routing_algorithm_metadata_by_merchant_id(
+        &self,
+        merchant_id: &str,
+        limit: i64,
+        offset: i64,
+    ) -> StorageResult<Vec<routing_storage::RoutingProfileMetadata>>;
+}
+
+#[async_trait::async_trait]
+impl RoutingAlgorithmInterface for Store {
+    async fn insert_routing_algorithm(
+        &self,
+        routing_algorithm: routing_storage::RoutingAlgorithm,
+    ) -> StorageResult<routing_storage::RoutingAlgorithm> {
+        let conn = connection::pg_connection_write(self).await?;
+        routing_algorithm
+            .insert(&conn)
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+
+    async fn find_routing_algorithm_by_profile_id_algorithm_id(
+        &self,
+        profile_id: &str,
+        algorithm_id: &str,
+    ) -> StorageResult<routing_storage::RoutingAlgorithm> {
+        let conn = connection::pg_connection_write(self).await?;
+        routing_storage::RoutingAlgorithm::find_by_algorithm_id_profile_id(
+            &conn,
+            algorithm_id,
+            profile_id,
+        )
+        .await
+        .map_err(Into::into)
+        .into_report()
+    }
+
+    async fn find_routing_algorithm_by_algorithm_id_merchant_id(
+        &self,
+        algorithm_id: &str,
+        merchant_id: &str,
+    ) -> StorageResult<routing_storage::RoutingAlgorithm> {
+        let conn = connection::pg_connection_write(self).await?;
+        routing_storage::RoutingAlgorithm::find_by_algorithm_id_merchant_id(
+            &conn,
+            algorithm_id,
+            merchant_id,
+        )
+        .await
+        .map_err(Into::into)
+        .into_report()
+    }
+
+    async fn find_routing_algorithm_metadata_by_algorithm_id_profile_id(
+        &self,
+        algorithm_id: &str,
+        profile_id: &str,
+    ) -> StorageResult<routing_storage::RoutingProfileMetadata> {
+        let conn = connection::pg_connection_write(self).await?;
+        routing_storage::RoutingAlgorithm::find_metadata_by_algorithm_id_profile_id(
+            &conn,
+            algorithm_id,
+            profile_id,
+        )
+        .await
+        .map_err(Into::into)
+        .into_report()
+    }
+
+    async fn list_routing_algorithm_metadata_by_profile_id(
+        &self,
+        profile_id: &str,
+        limit: i64,
+        offset: i64,
+    ) -> StorageResult<Vec<routing_storage::RoutingAlgorithmMetadata>> {
+        let conn = connection::pg_connection_write(self).await?;
+        routing_storage::RoutingAlgorithm::list_metadata_by_profile_id(
+            &conn, profile_id, limit, offset,
+        )
+        .await
+        .map_err(Into::into)
+        .into_report()
+    }
+
+    async fn list_routing_algorithm_metadata_by_merchant_id(
+        &self,
+        merchant_id: &str,
+        limit: i64,
+        offset: i64,
+    ) -> StorageResult<Vec<routing_storage::RoutingProfileMetadata>> {
+        let conn = connection::pg_connection_write(self).await?;
+        routing_storage::RoutingAlgorithm::list_metadata_by_merchant_id(
+            &conn,
+            merchant_id,
+            limit,
+            offset,
+        )
+        .await
+        .map_err(Into::into)
+        .into_report()
+    }
+}
+
+#[async_trait::async_trait]
+impl RoutingAlgorithmInterface for MockDb {
+    async fn insert_routing_algorithm(
+        &self,
+        _routing_algorithm: routing_storage::RoutingAlgorithm,
+    ) -> StorageResult<routing_storage::RoutingAlgorithm> {
+        Err(errors::StorageError::MockDbError)?
+    }
+
+    async fn find_routing_algorithm_by_profile_id_algorithm_id(
+        &self,
+        _profile_id: &str,
+        _algorithm_id: &str,
+    ) -> StorageResult<routing_storage::RoutingAlgorithm> {
+        Err(errors::StorageError::MockDbError)?
+    }
+
+    async fn find_routing_algorithm_by_algorithm_id_merchant_id(
+        &self,
+        _algorithm_id: &str,
+        _merchant_id: &str,
+    ) -> StorageResult<routing_storage::RoutingAlgorithm> {
+        Err(errors::StorageError::MockDbError)?
+    }
+
+    async fn find_routing_algorithm_metadata_by_algorithm_id_profile_id(
+        &self,
+        _algorithm_id: &str,
+        _profile_id: &str,
+    ) -> StorageResult<routing_storage::RoutingProfileMetadata> {
+        Err(errors::StorageError::MockDbError)?
+    }
+
+    async fn list_routing_algorithm_metadata_by_profile_id(
+        &self,
+        _profile_id: &str,
+        _limit: i64,
+        _offset: i64,
+    ) -> StorageResult<Vec<routing_storage::RoutingAlgorithmMetadata>> {
+        Err(errors::StorageError::MockDbError)?
+    }
+
+    async fn list_routing_algorithm_metadata_by_merchant_id(
+        &self,
+        _merchant_id: &str,
+        _limit: i64,
+        _offset: i64,
+    ) -> StorageResult<Vec<routing_storage::RoutingProfileMetadata>> {
+        Err(errors::StorageError::MockDbError)?
+    }
+}
diff --git a/crates/router/src/db/user.rs b/crates/router/src/db/user.rs
new file mode 100644
index 000000000000..6bb1d9e50b6a
--- /dev/null
+++ b/crates/router/src/db/user.rs
@@ -0,0 +1,265 @@
+use diesel_models::user as storage;
+use error_stack::{IntoReport, ResultExt};
+use masking::Secret;
+
+use super::MockDb;
+use crate::{
+    connection,
+    core::errors::{self, CustomResult},
+    services::Store,
+};
+
+#[async_trait::async_trait]
+pub trait UserInterface {
+    async fn insert_user(
+        &self,
+        user_data: storage::UserNew,
+    ) -> CustomResult<storage::User, errors::StorageError>;
+
+    async fn find_user_by_email(
+        &self,
+        user_email: &str,
+    ) -> CustomResult<storage::User, errors::StorageError>;
+
+    async fn find_user_by_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<storage::User, errors::StorageError>;
+
+    async fn update_user_by_user_id(
+        &self,
+        user_id: &str,
+        user: storage::UserUpdate,
+    ) -> CustomResult<storage::User, errors::StorageError>;
+
+    async fn delete_user_by_user_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<bool, errors::StorageError>;
+}
+
+#[async_trait::async_trait]
+impl UserInterface for Store {
+    async fn insert_user(
+        &self,
+        user_data: storage::UserNew,
+    ) -> CustomResult<storage::User, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        user_data
+            .insert(&conn)
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+
+    async fn find_user_by_email(
+        &self,
+        user_email: &str,
+    ) -> CustomResult<storage::User, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        storage::User::find_by_user_email(&conn, user_email)
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+
+    async fn find_user_by_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<storage::User, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        storage::User::find_by_user_id(&conn, user_id)
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+
+    async fn update_user_by_user_id(
+        &self,
+        user_id: &str,
+        user: storage::UserUpdate,
+    ) -> CustomResult<storage::User, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        storage::User::update_by_user_id(&conn, user_id, user)
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+
+    async fn delete_user_by_user_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<bool, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        storage::User::delete_by_user_id(&conn, user_id)
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+}
+
+#[async_trait::async_trait]
+impl UserInterface for MockDb {
+    async fn insert_user(
+        &self,
+        user_data: storage::UserNew,
+    ) -> CustomResult<storage::User, errors::StorageError> {
+        let mut users = self.users.lock().await;
+        if users
+            .iter()
+            .any(|user| user.email == user_data.email || user.user_id == user_data.user_id)
+        {
+            Err(errors::StorageError::DuplicateValue {
+                entity: "email or user_id",
+                key: None,
+            })?
+        }
+        let time_now = common_utils::date_time::now();
+        let user = storage::User {
+            id: users
+                .len()
+                .try_into()
+                .into_report()
+                .change_context(errors::StorageError::MockDbError)?,
+            user_id: user_data.user_id,
+            email: user_data.email,
+            name: user_data.name,
+            password: user_data.password,
+            is_verified: user_data.is_verified,
+            created_at: user_data.created_at.unwrap_or(time_now),
+            last_modified_at: user_data.created_at.unwrap_or(time_now),
+        };
+        users.push(user.clone());
+        Ok(user)
+    }
+
+    async fn find_user_by_email(
+        &self,
+        user_email: &str,
+    ) -> CustomResult<storage::User, errors::StorageError> {
+        let users = self.users.lock().await;
+        let user_email_pii: common_utils::pii::Email = user_email
+            .to_string()
+            .try_into()
+            .map_err(|_| errors::StorageError::MockDbError)?;
+        users
+            .iter()
+            .find(|user| user.email == user_email_pii)
+            .cloned()
+            .ok_or(
+                errors::StorageError::ValueNotFound(format!(
+                    "No user available for email = {user_email}"
+                ))
+                .into(),
+            )
+    }
+
+    async fn find_user_by_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<storage::User, errors::StorageError> {
+        let users = self.users.lock().await;
+        users
+            .iter()
+            .find(|user| user.user_id == user_id)
+            .cloned()
+            .ok_or(
+                errors::StorageError::ValueNotFound(format!(
+                    "No user available for user_id = {user_id}"
+                ))
+                .into(),
+            )
+    }
+
+    async fn update_user_by_user_id(
+        &self,
+        user_id: &str,
+        update_user: storage::UserUpdate,
+    ) -> CustomResult<storage::User, errors::StorageError> {
+        let mut users = self.users.lock().await;
+        users
+            .iter_mut()
+            .find(|user| user.user_id == user_id)
+            .map(|user| {
+                *user = match &update_user {
+                    storage::UserUpdate::VerifyUser => storage::User {
+                        is_verified: true,
+                        ..user.to_owned()
+                    },
+                    storage::UserUpdate::AccountUpdate {
+                        name,
+                        password,
+                        is_verified,
+                    } => storage::User {
+                        name: name.clone().map(Secret::new).unwrap_or(user.name.clone()),
+                        password: password.clone().unwrap_or(user.password.clone()),
+                        is_verified: is_verified.unwrap_or(user.is_verified),
+                        ..user.to_owned()
+                    },
+                };
+                user.to_owned()
+            })
+            .ok_or(
+                errors::StorageError::ValueNotFound(format!(
+                    "No user available for user_id = {user_id}"
+                ))
+                .into(),
+            )
+    }
+
+    async fn delete_user_by_user_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<bool, errors::StorageError> {
+        let mut users = self.users.lock().await;
+        let user_index = users
+            .iter()
+            .position(|user| user.user_id == user_id)
+            .ok_or(errors::StorageError::ValueNotFound(format!(
+                "No user available for user_id = {user_id}"
+            )))?;
+        users.remove(user_index);
+        Ok(true)
+    }
+}
+#[cfg(feature = "kafka_events")]
+#[async_trait::async_trait]
+impl UserInterface for super::KafkaStore {
+    async fn insert_user(
+        &self,
+        user_data: storage::UserNew,
+    ) -> CustomResult<storage::User, errors::StorageError> {
+        self.diesel_store.insert_user(user_data).await
+    }
+
+    async fn find_user_by_email(
+        &self,
+        user_email: &str,
+    ) -> CustomResult<storage::User, errors::StorageError> {
+        self.diesel_store.find_user_by_email(user_email).await
+    }
+
+    async fn find_user_by_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<storage::User, errors::StorageError> {
+        self.diesel_store.find_user_by_id(user_id).await
+    }
+
+    async fn update_user_by_user_id(
+        &self,
+        user_id: &str,
+        user: storage::UserUpdate,
+    ) -> CustomResult<storage::User, errors::StorageError> {
+        self.diesel_store
+            .update_user_by_user_id(user_id, user)
+            .await
+    }
+
+    async fn delete_user_by_user_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<bool, errors::StorageError> {
+        self.diesel_store.delete_user_by_user_id(user_id).await
+    }
+}
diff --git a/crates/router/src/db/user_role.rs b/crates/router/src/db/user_role.rs
new file mode 100644
index 000000000000..37e38e8afca7
--- /dev/null
+++ b/crates/router/src/db/user_role.rs
@@ -0,0 +1,255 @@
+use diesel_models::user_role as storage;
+use error_stack::{IntoReport, ResultExt};
+
+use super::MockDb;
+use crate::{
+    connection,
+    core::errors::{self, CustomResult},
+    services::Store,
+};
+
+#[async_trait::async_trait]
+pub trait UserRoleInterface {
+    async fn insert_user_role(
+        &self,
+        user_role: storage::UserRoleNew,
+    ) -> CustomResult<storage::UserRole, errors::StorageError>;
+    async fn find_user_role_by_user_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<storage::UserRole, errors::StorageError>;
+    async fn update_user_role_by_user_id_merchant_id(
+        &self,
+        user_id: &str,
+        merchant_id: &str,
+        update: storage::UserRoleUpdate,
+    ) -> CustomResult<storage::UserRole, errors::StorageError>;
+    async fn delete_user_role(&self, user_id: &str) -> CustomResult<bool, errors::StorageError>;
+
+    async fn list_user_roles_by_user_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError>;
+}
+
+#[async_trait::async_trait]
+impl UserRoleInterface for Store {
+    async fn insert_user_role(
+        &self,
+        user_role: storage::UserRoleNew,
+    ) -> CustomResult<storage::UserRole, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        user_role
+            .insert(&conn)
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+
+    async fn find_user_role_by_user_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<storage::UserRole, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        storage::UserRole::find_by_user_id(&conn, user_id.to_owned())
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+
+    async fn update_user_role_by_user_id_merchant_id(
+        &self,
+        user_id: &str,
+        merchant_id: &str,
+        update: storage::UserRoleUpdate,
+    ) -> CustomResult<storage::UserRole, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        storage::UserRole::update_by_user_id_merchant_id(
+            &conn,
+            user_id.to_owned(),
+            merchant_id.to_owned(),
+            update,
+        )
+        .await
+        .map_err(Into::into)
+        .into_report()
+    }
+
+    async fn delete_user_role(&self, user_id: &str) -> CustomResult<bool, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        storage::UserRole::delete_by_user_id(&conn, user_id.to_owned())
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+
+    async fn list_user_roles_by_user_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        storage::UserRole::list_by_user_id(&conn, user_id.to_owned())
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+}
+
+#[async_trait::async_trait]
+impl UserRoleInterface for MockDb {
+    async fn insert_user_role(
+        &self,
+        user_role: storage::UserRoleNew,
+    ) -> CustomResult<storage::UserRole, errors::StorageError> {
+        let mut user_roles = self.user_roles.lock().await;
+        if user_roles
+            .iter()
+            .any(|user_role_inner| user_role_inner.user_id == user_role.user_id)
+        {
+            Err(errors::StorageError::DuplicateValue {
+                entity: "user_id",
+                key: None,
+            })?
+        }
+        let user_role = storage::UserRole {
+            id: user_roles
+                .len()
+                .try_into()
+                .into_report()
+                .change_context(errors::StorageError::MockDbError)?,
+            user_id: user_role.user_id,
+            merchant_id: user_role.merchant_id,
+            role_id: user_role.role_id,
+            status: user_role.status,
+            created_by: user_role.created_by,
+            created_at: user_role.created_at,
+            last_modified_at: user_role.last_modified_at,
+            last_modified_by: user_role.last_modified_by,
+            org_id: user_role.org_id,
+        };
+        user_roles.push(user_role.clone());
+        Ok(user_role)
+    }
+
+    async fn find_user_role_by_user_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<storage::UserRole, errors::StorageError> {
+        let user_roles = self.user_roles.lock().await;
+        user_roles
+            .iter()
+            .find(|user_role| user_role.user_id == user_id)
+            .cloned()
+            .ok_or(
+                errors::StorageError::ValueNotFound(format!(
+                    "No user role available for user_id = {user_id}"
+                ))
+                .into(),
+            )
+    }
+
+    async fn update_user_role_by_user_id_merchant_id(
+        &self,
+        user_id: &str,
+        merchant_id: &str,
+        update: storage::UserRoleUpdate,
+    ) -> CustomResult<storage::UserRole, errors::StorageError> {
+        let mut user_roles = self.user_roles.lock().await;
+        user_roles
+            .iter_mut()
+            .find(|user_role| user_role.user_id == user_id && user_role.merchant_id == merchant_id)
+            .map(|user_role| {
+                *user_role = match &update {
+                    storage::UserRoleUpdate::UpdateRole {
+                        role_id,
+                        modified_by,
+                    } => storage::UserRole {
+                        role_id: role_id.to_string(),
+                        last_modified_by: modified_by.to_string(),
+                        ..user_role.to_owned()
+                    },
+                    storage::UserRoleUpdate::UpdateStatus {
+                        status,
+                        modified_by,
+                    } => storage::UserRole {
+                        status: status.to_owned(),
+                        last_modified_by: modified_by.to_owned(),
+                        ..user_role.to_owned()
+                    },
+                };
+                user_role.to_owned()
+            })
+            .ok_or(
+                errors::StorageError::ValueNotFound(format!(
+                    "No user role available for user_id = {user_id} and merchant_id = {merchant_id}"
+                ))
+                .into(),
+            )
+    }
+
+    async fn delete_user_role(&self, user_id: &str) -> CustomResult<bool, errors::StorageError> {
+        let mut user_roles = self.user_roles.lock().await;
+        let user_role_index = user_roles
+            .iter()
+            .position(|user_role| user_role.user_id == user_id)
+            .ok_or(errors::StorageError::ValueNotFound(format!(
+                "No user available for user_id = {user_id}"
+            )))?;
+        user_roles.remove(user_role_index);
+        Ok(true)
+    }
+
+    async fn list_user_roles_by_user_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError> {
+        let user_roles = self.user_roles.lock().await;
+
+        Ok(user_roles
+            .iter()
+            .cloned()
+            .filter_map(|ele| {
+                if ele.user_id == user_id {
+                    return Some(ele);
+                }
+                None
+            })
+            .collect())
+    }
+}
+
+#[cfg(feature = "kafka_events")]
+#[async_trait::async_trait]
+impl UserRoleInterface for super::KafkaStore {
+    async fn insert_user_role(
+        &self,
+        user_role: storage::UserRoleNew,
+    ) -> CustomResult<storage::UserRole, errors::StorageError> {
+        self.diesel_store.insert_user_role(user_role).await
+    }
+    async fn update_user_role_by_user_id_merchant_id(
+        &self,
+        user_id: &str,
+        merchant_id: &str,
+        update: storage::UserRoleUpdate,
+    ) -> CustomResult<storage::UserRole, errors::StorageError> {
+        self.diesel_store
+            .update_user_role_by_user_id_merchant_id(user_id, merchant_id, update)
+            .await
+    }
+    async fn find_user_role_by_user_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<storage::UserRole, errors::StorageError> {
+        self.diesel_store.find_user_role_by_user_id(user_id).await
+    }
+    async fn delete_user_role(&self, user_id: &str) -> CustomResult<bool, errors::StorageError> {
+        self.diesel_store.delete_user_role(user_id).await
+    }
+    async fn list_user_roles_by_user_id(
+        &self,
+        user_id: &str,
+    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError> {
+        self.diesel_store.list_user_roles_by_user_id(user_id).await
+    }
+}
diff --git a/crates/router/src/events.rs b/crates/router/src/events.rs
index 88d7ff668490..39a8543a68c4 100644
--- a/crates/router/src/events.rs
+++ b/crates/router/src/events.rs
@@ -9,13 +9,14 @@ pub trait EventHandler: Sync + Send + dyn_clone::DynClone {
 
 dyn_clone::clone_trait_object!(EventHandler);
 
+#[derive(Debug)]
 pub struct RawEvent {
-    event_type: EventType,
-    key: String,
-    payload: serde_json::Value,
+    pub event_type: EventType,
+    pub key: String,
+    pub payload: serde_json::Value,
 }
 
-#[derive(Debug, Serialize)]
+#[derive(Debug, Serialize, Clone, Copy)]
 #[serde(rename_all = "snake_case")]
 pub enum EventType {
     PaymentIntent,
diff --git a/crates/router/src/events/api_logs.rs b/crates/router/src/events/api_logs.rs
index 784d80b278da..27a90028ba6a 100644
--- a/crates/router/src/events/api_logs.rs
+++ b/crates/router/src/events/api_logs.rs
@@ -1,24 +1,59 @@
+use actix_web::HttpRequest;
+pub use common_utils::events::{ApiEventMetric, ApiEventsType};
+use common_utils::impl_misc_api_event_type;
 use router_env::{tracing_actix_web::RequestId, types::FlowMetric};
-use serde::{Deserialize, Serialize};
+use serde::Serialize;
 use time::OffsetDateTime;
 
 use super::{EventType, RawEvent};
+#[cfg(feature = "dummy_connector")]
+use crate::routes::dummy_connector::types::{
+    DummyConnectorPaymentCompleteRequest, DummyConnectorPaymentConfirmRequest,
+    DummyConnectorPaymentRequest, DummyConnectorPaymentResponse,
+    DummyConnectorPaymentRetrieveRequest, DummyConnectorRefundRequest,
+    DummyConnectorRefundResponse, DummyConnectorRefundRetrieveRequest,
+};
+use crate::{
+    core::payments::PaymentsRedirectResponseData,
+    services::{authentication::AuthenticationType, ApplicationResponse, PaymentLinkFormData},
+    types::api::{
+        AttachEvidenceRequest, Config, ConfigUpdate, CreateFileRequest, DisputeId, FileId,
+    },
+};
 
-#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
+#[serde(rename_all = "snake_case")]
 pub struct ApiEvent {
     api_flow: String,
     created_at_timestamp: i128,
     request_id: String,
     latency: u128,
     status_code: i64,
+    #[serde(flatten)]
+    auth_type: AuthenticationType,
+    request: serde_json::Value,
+    user_agent: Option<String>,
+    ip_addr: Option<String>,
+    url_path: String,
+    response: Option<serde_json::Value>,
+    #[serde(flatten)]
+    event_type: ApiEventsType,
+    hs_latency: Option<u128>,
 }
 
 impl ApiEvent {
+    #[allow(clippy::too_many_arguments)]
     pub fn new(
         api_flow: &impl FlowMetric,
         request_id: &RequestId,
         latency: u128,
         status_code: i64,
+        request: serde_json::Value,
+        response: Option<serde_json::Value>,
+        hs_latency: Option<u128>,
+        auth_type: AuthenticationType,
+        event_type: ApiEventsType,
+        http_req: &HttpRequest,
     ) -> Self {
         Self {
             api_flow: api_flow.to_string(),
@@ -26,6 +61,20 @@ impl ApiEvent {
             request_id: request_id.as_hyphenated().to_string(),
             latency,
             status_code,
+            request,
+            response,
+            auth_type,
+            ip_addr: http_req
+                .connection_info()
+                .realip_remote_addr()
+                .map(ToOwned::to_owned),
+            user_agent: http_req
+                .headers()
+                .get("user-agent")
+                .and_then(|user_agent_value| user_agent_value.to_str().ok().map(ToOwned::to_owned)),
+            url_path: http_req.path().to_string(),
+            event_type,
+            hs_latency,
         }
     }
 }
@@ -41,3 +90,35 @@ impl TryFrom<ApiEvent> for RawEvent {
         })
     }
 }
+
+impl<T: ApiEventMetric> ApiEventMetric for ApplicationResponse<T> {
+    fn get_api_event_type(&self) -> Option<ApiEventsType> {
+        match self {
+            Self::Json(r) => r.get_api_event_type(),
+            Self::JsonWithHeaders((r, _)) => r.get_api_event_type(),
+            _ => None,
+        }
+    }
+}
+impl_misc_api_event_type!(
+    Config,
+    CreateFileRequest,
+    FileId,
+    AttachEvidenceRequest,
+    DisputeId,
+    PaymentLinkFormData,
+    PaymentsRedirectResponseData,
+    ConfigUpdate
+);
+
+#[cfg(feature = "dummy_connector")]
+impl_misc_api_event_type!(
+    DummyConnectorPaymentCompleteRequest,
+    DummyConnectorPaymentRequest,
+    DummyConnectorPaymentResponse,
+    DummyConnectorPaymentRetrieveRequest,
+    DummyConnectorPaymentConfirmRequest,
+    DummyConnectorRefundRetrieveRequest,
+    DummyConnectorRefundResponse,
+    DummyConnectorRefundRequest
+);
diff --git a/crates/router/src/lib.rs b/crates/router/src/lib.rs
index 11efec64055b..a3ed0b35c785 100644
--- a/crates/router/src/lib.rs
+++ b/crates/router/src/lib.rs
@@ -1,6 +1,8 @@
 #![forbid(unsafe_code)]
 #![recursion_limit = "256"]
 
+#[cfg(feature = "olap")]
+pub mod analytics;
 #[cfg(feature = "stripe")]
 pub mod compatibility;
 pub mod configs;
@@ -141,6 +143,10 @@ pub fn mk_app(
             .service(routes::ApiKeys::server(state.clone()))
             .service(routes::Files::server(state.clone()))
             .service(routes::Disputes::server(state.clone()))
+            .service(routes::Analytics::server(state.clone()))
+            .service(routes::Routing::server(state.clone()))
+            .service(routes::Gsm::server(state.clone()))
+            .service(routes::User::server(state.clone()))
     }
 
     #[cfg(all(feature = "olap", feature = "kms"))]
@@ -183,7 +189,7 @@ pub async fn start_server(conf: settings::Settings) -> ApplicationResult<Server>
             errors::ApplicationError::ApiClientError(error.current_context().clone())
         })?,
     );
-    let state = routes::AppState::new(conf, tx, api_client).await;
+    let state = Box::pin(routes::AppState::new(conf, tx, api_client)).await;
     let request_body_limit = server.request_body_limit;
     let server = actix_web::HttpServer::new(move || mk_app(state.clone(), request_body_limit))
         .bind((server.host.as_str(), server.port))?
diff --git a/crates/router/src/openapi.rs b/crates/router/src/openapi.rs
index a5bce200889b..dbcd8cbe4ce2 100644
--- a/crates/router/src/openapi.rs
+++ b/crates/router/src/openapi.rs
@@ -305,7 +305,7 @@ Never share your secret api keys. Keep them guarded and secure.
         api_models::payment_methods::RequiredFieldInfo,
         api_models::refunds::RefundListRequest,
         api_models::refunds::RefundListResponse,
-        api_models::refunds::TimeRange,
+        api_models::payments::TimeRange,
         api_models::mandates::MandateRevokedResponse,
         api_models::mandates::MandateResponse,
         api_models::mandates::MandateCardDetails,
diff --git a/crates/router/src/routes.rs b/crates/router/src/routes.rs
index 307797e8ac9d..745433c2074b 100644
--- a/crates/router/src/routes.rs
+++ b/crates/router/src/routes.rs
@@ -10,6 +10,7 @@ pub mod disputes;
 pub mod dummy_connector;
 pub mod ephemeral_key;
 pub mod files;
+pub mod gsm;
 pub mod health;
 pub mod lock_utils;
 pub mod mandates;
@@ -20,6 +21,10 @@ pub mod payments;
 #[cfg(feature = "payouts")]
 pub mod payouts;
 pub mod refunds;
+#[cfg(feature = "olap")]
+pub mod routing;
+#[cfg(feature = "olap")]
+pub mod user;
 #[cfg(all(feature = "olap", feature = "kms"))]
 pub mod verification;
 pub mod webhooks;
@@ -28,12 +33,16 @@ pub mod webhooks;
 pub use self::app::DummyConnector;
 #[cfg(feature = "payouts")]
 pub use self::app::Payouts;
+#[cfg(feature = "olap")]
+pub use self::app::Routing;
 #[cfg(all(feature = "olap", feature = "kms"))]
 pub use self::app::Verify;
 pub use self::app::{
     ApiKeys, AppState, BusinessProfile, Cache, Cards, Configs, Customers, Disputes, EphemeralKey,
-    Files, Health, Mandates, MerchantAccount, MerchantConnectorAccount, PaymentLink,
-    PaymentMethods, Payments, Refunds, Webhooks,
+    Files, Gsm, Health, Mandates, MerchantAccount, MerchantConnectorAccount, PaymentLink,
+    PaymentMethods, Payments, Refunds, User, Webhooks,
 };
 #[cfg(feature = "stripe")]
 pub use super::compatibility::stripe::StripeApis;
+#[cfg(feature = "olap")]
+pub use crate::analytics::routes::{self as analytics, Analytics};
diff --git a/crates/router/src/routes/admin.rs b/crates/router/src/routes/admin.rs
index a93556202aab..eef8cacc5f92 100644
--- a/crates/router/src/routes/admin.rs
+++ b/crates/router/src/routes/admin.rs
@@ -30,7 +30,7 @@ pub async fn merchant_account_create(
     json_payload: web::Json<admin::MerchantAccountCreate>,
 ) -> HttpResponse {
     let flow = Flow::MerchantsAccountCreate;
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -38,7 +38,7 @@ pub async fn merchant_account_create(
         |state, _, req| create_merchant_account(state, req),
         &auth::AdminApiAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Merchant Account - Retrieve
@@ -64,7 +64,10 @@ pub async fn retrieve_merchant_account(
 ) -> HttpResponse {
     let flow = Flow::MerchantsAccountRetrieve;
     let merchant_id = mid.into_inner();
-    let payload = web::Json(admin::MerchantId { merchant_id }).into_inner();
+    let payload = web::Json(admin::MerchantId {
+        merchant_id: merchant_id.to_owned(),
+    })
+    .into_inner();
 
     api::server_wrap(
         flow,
@@ -72,7 +75,11 @@ pub async fn retrieve_merchant_account(
         &req,
         payload,
         |state, _, req| get_merchant_account(state, req),
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute { merchant_id },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
     )
     .await
@@ -124,15 +131,21 @@ pub async fn update_merchant_account(
 ) -> HttpResponse {
     let flow = Flow::MerchantsAccountUpdate;
     let merchant_id = mid.into_inner();
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
         json_payload.into_inner(),
         |state, _, req| merchant_account_update(state, &merchant_id, req),
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute {
+                merchant_id: merchant_id.clone(),
+            },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 
@@ -197,15 +210,21 @@ pub async fn payment_connector_create(
 ) -> HttpResponse {
     let flow = Flow::MerchantConnectorsCreate;
     let merchant_id = path.into_inner();
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
         json_payload.into_inner(),
         |state, _, req| create_payment_connector(state, req, &merchant_id),
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute {
+                merchant_id: merchant_id.clone(),
+            },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Merchant Connector - Retrieve
@@ -236,7 +255,7 @@ pub async fn payment_connector_retrieve(
     let flow = Flow::MerchantConnectorsRetrieve;
     let (merchant_id, merchant_connector_id) = path.into_inner();
     let payload = web::Json(admin::MerchantConnectorId {
-        merchant_id,
+        merchant_id: merchant_id.clone(),
         merchant_connector_id,
     })
     .into_inner();
@@ -249,7 +268,11 @@ pub async fn payment_connector_retrieve(
         |state, _, req| {
             retrieve_payment_connector(state, req.merchant_id, req.merchant_connector_id)
         },
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute { merchant_id },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
     )
     .await
@@ -285,9 +308,13 @@ pub async fn payment_connector_list(
         flow,
         state,
         &req,
-        merchant_id,
+        merchant_id.to_owned(),
         |state, _, merchant_id| list_payment_connectors(state, merchant_id),
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute { merchant_id },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
     )
     .await
@@ -328,7 +355,13 @@ pub async fn payment_connector_update(
         &req,
         json_payload.into_inner(),
         |state, _, req| update_payment_connector(state, &merchant_id, &merchant_connector_id, req),
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute {
+                merchant_id: merchant_id.clone(),
+            },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
     )
     .await
@@ -362,7 +395,7 @@ pub async fn payment_connector_delete(
     let (merchant_id, merchant_connector_id) = path.into_inner();
 
     let payload = web::Json(admin::MerchantConnectorId {
-        merchant_id,
+        merchant_id: merchant_id.clone(),
         merchant_connector_id,
     })
     .into_inner();
@@ -372,7 +405,11 @@ pub async fn payment_connector_delete(
         &req,
         payload,
         |state, _, req| delete_payment_connector(state, req.merchant_id, req.merchant_connector_id),
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute { merchant_id },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
     )
     .await
@@ -388,15 +425,15 @@ pub async fn merchant_account_toggle_kv(
     json_payload: web::Json<admin::ToggleKVRequest>,
 ) -> HttpResponse {
     let flow = Flow::ConfigKeyUpdate;
-    let payload = json_payload.into_inner();
-    let merchant_id = path.into_inner();
+    let mut payload = json_payload.into_inner();
+    payload.merchant_id = path.into_inner();
 
     api::server_wrap(
         flow,
         state,
         &req,
-        (merchant_id, payload),
-        |state, _, (merchant_id, payload)| kv_for_merchant(state, merchant_id, payload.kv_enabled),
+        payload,
+        |state, _, payload| kv_for_merchant(state, payload.merchant_id, payload.kv_enabled),
         &auth::AdminApiAuth,
         api_locking::LockAction::NotApplicable,
     )
@@ -413,15 +450,21 @@ pub async fn business_profile_create(
     let payload = json_payload.into_inner();
     let merchant_id = path.into_inner();
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
         payload,
         |state, _, req| create_business_profile(state, req, &merchant_id),
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute {
+                merchant_id: merchant_id.clone(),
+            },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 #[instrument(skip_all, fields(flow = ?Flow::BusinessProfileRetrieve))]
@@ -431,7 +474,7 @@ pub async fn business_profile_retrieve(
     path: web::Path<(String, String)>,
 ) -> HttpResponse {
     let flow = Flow::BusinessProfileRetrieve;
-    let (_, profile_id) = path.into_inner();
+    let (merchant_id, profile_id) = path.into_inner();
 
     api::server_wrap(
         flow,
@@ -439,7 +482,11 @@ pub async fn business_profile_retrieve(
         &req,
         profile_id,
         |state, _, profile_id| retrieve_business_profile(state, profile_id),
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute { merchant_id },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
     )
     .await
@@ -460,7 +507,13 @@ pub async fn business_profile_update(
         &req,
         json_payload.into_inner(),
         |state, _, req| update_business_profile(state, &profile_id, &merchant_id, req),
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute {
+                merchant_id: merchant_id.clone(),
+            },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
     )
     .await
@@ -498,9 +551,13 @@ pub async fn business_profiles_list(
         flow,
         state,
         &req,
-        merchant_id,
+        merchant_id.clone(),
         |state, _, merchant_id| list_business_profile(state, merchant_id),
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute { merchant_id },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
     )
     .await
diff --git a/crates/router/src/routes/api_keys.rs b/crates/router/src/routes/api_keys.rs
index 6057b4c5db24..7299aa696390 100644
--- a/crates/router/src/routes/api_keys.rs
+++ b/crates/router/src/routes/api_keys.rs
@@ -36,7 +36,7 @@ pub async fn api_key_create(
     let payload = json_payload.into_inner();
     let merchant_id = path.into_inner();
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -53,9 +53,15 @@ pub async fn api_key_create(
             )
             .await
         },
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute {
+                merchant_id: merchant_id.clone(),
+            },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// API Key - Retrieve
@@ -91,7 +97,13 @@ pub async fn api_key_retrieve(
         &req,
         (&merchant_id, &key_id),
         |state, _, (merchant_id, key_id)| api_keys::retrieve_api_key(state, merchant_id, key_id),
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute {
+                merchant_id: merchant_id.clone(),
+            },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
     )
     .await
@@ -124,16 +136,16 @@ pub async fn api_key_update(
 ) -> impl Responder {
     let flow = Flow::ApiKeyUpdate;
     let (merchant_id, key_id) = path.into_inner();
-    let payload = json_payload.into_inner();
+    let mut payload = json_payload.into_inner();
+    payload.key_id = key_id;
+    payload.merchant_id = merchant_id;
 
     api::server_wrap(
         flow,
         state,
         &req,
-        (&merchant_id, &key_id, payload),
-        |state, _, (merchant_id, key_id, payload)| {
-            api_keys::update_api_key(state, merchant_id, key_id, payload)
-        },
+        payload,
+        |state, _, payload| api_keys::update_api_key(state, payload),
         &auth::AdminApiAuth,
         api_locking::LockAction::NotApplicable,
     )
@@ -173,7 +185,13 @@ pub async fn api_key_revoke(
         &req,
         (&merchant_id, &key_id),
         |state, _, (merchant_id, key_id)| api_keys::revoke_api_key(state, merchant_id, key_id),
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute {
+                merchant_id: merchant_id.clone(),
+            },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
     )
     .await
@@ -213,11 +231,15 @@ pub async fn api_key_list(
         flow,
         state,
         &req,
-        (limit, offset, merchant_id),
+        (limit, offset, merchant_id.clone()),
         |state, _, (limit, offset, merchant_id)| async move {
             api_keys::list_api_keys(state, merchant_id, limit, offset).await
         },
-        &auth::AdminApiAuth,
+        auth::auth_type(
+            &auth::AdminApiAuth,
+            &auth::JWTAuthMerchantFromRoute { merchant_id },
+            req.headers(),
+        ),
         api_locking::LockAction::NotApplicable,
     )
     .await
diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs
index 3d9295794886..15b6df733489 100644
--- a/crates/router/src/routes/app.rs
+++ b/crates/router/src/routes/app.rs
@@ -14,10 +14,12 @@ use tokio::sync::oneshot;
 use super::dummy_connector::*;
 #[cfg(feature = "payouts")]
 use super::payouts::*;
+#[cfg(feature = "olap")]
+use super::routing as cloud_routing;
 #[cfg(all(feature = "olap", feature = "kms"))]
 use super::verification::{apple_pay_merchant_registration, retrieve_apple_pay_verified_domains};
 #[cfg(feature = "olap")]
-use super::{admin::*, api_keys::*, disputes::*, files::*};
+use super::{admin::*, api_keys::*, disputes::*, files::*, gsm::*, user::*};
 use super::{cache::*, health::*, payment_link::*};
 #[cfg(any(feature = "olap", feature = "oltp"))]
 use super::{configs::*, customers::*, mandates::*, payments::*, refunds::*};
@@ -42,6 +44,8 @@ pub struct AppState {
     #[cfg(feature = "kms")]
     pub kms_secrets: Arc<settings::ActiveKmsSecrets>,
     pub api_client: Box<dyn crate::services::ApiClient>,
+    #[cfg(feature = "olap")]
+    pub pool: crate::analytics::AnalyticsProvider,
 }
 
 impl scheduler::SchedulerAppState for AppState {
@@ -78,7 +82,9 @@ impl AppStateInfo for AppState {
     }
     fn add_request_id(&mut self, request_id: RequestId) {
         self.api_client.add_request_id(request_id);
+        self.store.add_request_id(request_id.to_string())
     }
+
     fn add_merchant_id(&mut self, merchant_id: Option<String>) {
         self.api_client.add_merchant_id(merchant_id);
     }
@@ -106,52 +112,59 @@ impl AppState {
         shut_down_signal: oneshot::Sender<()>,
         api_client: Box<dyn crate::services::ApiClient>,
     ) -> Self {
-        #[cfg(feature = "kms")]
-        let kms_client = kms::get_kms_client(&conf.kms).await;
-        let testable = storage_impl == StorageImpl::PostgresqlTest;
-        let store: Box<dyn StorageInterface> = match storage_impl {
-            StorageImpl::Postgresql | StorageImpl::PostgresqlTest => Box::new(
+        Box::pin(async move {
+            #[cfg(feature = "kms")]
+            let kms_client = kms::get_kms_client(&conf.kms).await;
+            let testable = storage_impl == StorageImpl::PostgresqlTest;
+            let store: Box<dyn StorageInterface> = match storage_impl {
+                StorageImpl::Postgresql | StorageImpl::PostgresqlTest => Box::new(
+                    #[allow(clippy::expect_used)]
+                    get_store(&conf, shut_down_signal, testable)
+                        .await
+                        .expect("Failed to create store"),
+                ),
                 #[allow(clippy::expect_used)]
-                get_store(&conf, shut_down_signal, testable)
-                    .await
-                    .expect("Failed to create store"),
-            ),
-            #[allow(clippy::expect_used)]
-            StorageImpl::Mock => Box::new(
-                MockDb::new(&conf.redis)
-                    .await
-                    .expect("Failed to create mock store"),
-            ),
-        };
-
-        #[cfg(feature = "kms")]
-        #[allow(clippy::expect_used)]
-        let kms_secrets = settings::ActiveKmsSecrets {
-            jwekey: conf.jwekey.clone().into(),
-            redis_temp_locker_encryption_key: conf
-                .locker
-                .redis_temp_locker_encryption_key
-                .clone()
-                .into(),
-        }
-        .decrypt_inner(kms_client)
-        .await
-        .expect("Failed while performing KMS decryption");
+                StorageImpl::Mock => Box::new(
+                    MockDb::new(&conf.redis)
+                        .await
+                        .expect("Failed to create mock store"),
+                ),
+            };
+
+            #[cfg(feature = "olap")]
+            let pool = crate::analytics::AnalyticsProvider::from_conf(
+                &conf.analytics,
+                #[cfg(feature = "kms")]
+                kms_client,
+            )
+            .await;
 
-        #[cfg(feature = "email")]
-        let email_client = Arc::new(AwsSes::new(&conf.email).await);
+            #[cfg(feature = "kms")]
+            #[allow(clippy::expect_used)]
+            let kms_secrets = settings::ActiveKmsSecrets {
+                jwekey: conf.jwekey.clone().into(),
+            }
+            .decrypt_inner(kms_client)
+            .await
+            .expect("Failed while performing KMS decryption");
 
-        Self {
-            flow_name: String::from("default"),
-            store,
-            conf: Arc::new(conf),
             #[cfg(feature = "email")]
-            email_client,
-            #[cfg(feature = "kms")]
-            kms_secrets: Arc::new(kms_secrets),
-            api_client,
-            event_handler: Box::<EventLogger>::default(),
-        }
+            let email_client = Arc::new(AwsSes::new(&conf.email).await);
+            Self {
+                flow_name: String::from("default"),
+                store,
+                conf: Arc::new(conf),
+                #[cfg(feature = "email")]
+                email_client,
+                #[cfg(feature = "kms")]
+                kms_secrets: Arc::new(kms_secrets),
+                api_client,
+                event_handler: Box::<EventLogger>::default(),
+                #[cfg(feature = "olap")]
+                pool,
+            }
+        })
+        .await
     }
 
     pub async fn new(
@@ -159,7 +172,13 @@ impl AppState {
         shut_down_signal: oneshot::Sender<()>,
         api_client: Box<dyn crate::services::ApiClient>,
     ) -> Self {
-        Self::with_storage(conf, StorageImpl::Postgresql, shut_down_signal, api_client).await
+        Box::pin(Self::with_storage(
+            conf,
+            StorageImpl::Postgresql,
+            shut_down_signal,
+            api_client,
+        ))
+        .await
     }
 }
 
@@ -280,6 +299,53 @@ impl Payments {
     }
 }
 
+#[cfg(feature = "olap")]
+pub struct Routing;
+
+#[cfg(feature = "olap")]
+impl Routing {
+    pub fn server(state: AppState) -> Scope {
+        web::scope("/routing")
+            .app_data(web::Data::new(state.clone()))
+            .service(
+                web::resource("/active")
+                    .route(web::get().to(cloud_routing::routing_retrieve_linked_config)),
+            )
+            .service(
+                web::resource("")
+                    .route(web::get().to(cloud_routing::routing_retrieve_dictionary))
+                    .route(web::post().to(cloud_routing::routing_create_config)),
+            )
+            .service(
+                web::resource("/default")
+                    .route(web::get().to(cloud_routing::routing_retrieve_default_config))
+                    .route(web::post().to(cloud_routing::routing_update_default_config)),
+            )
+            .service(
+                web::resource("/deactivate")
+                    .route(web::post().to(cloud_routing::routing_unlink_config)),
+            )
+            .service(
+                web::resource("/{algorithm_id}")
+                    .route(web::get().to(cloud_routing::routing_retrieve_config)),
+            )
+            .service(
+                web::resource("/{algorithm_id}/activate")
+                    .route(web::post().to(cloud_routing::routing_link_config)),
+            )
+            .service(
+                web::resource("/default/profile/{profile_id}").route(
+                    web::post().to(cloud_routing::routing_update_default_config_for_profile),
+                ),
+            )
+            .service(
+                web::resource("/default/profile").route(
+                    web::get().to(cloud_routing::routing_retrieve_default_config_for_profiles),
+                ),
+            )
+    }
+}
+
 pub struct Customers;
 
 #[cfg(any(feature = "olap", feature = "oltp"))]
@@ -631,6 +697,20 @@ impl BusinessProfile {
     }
 }
 
+pub struct Gsm;
+
+#[cfg(feature = "olap")]
+impl Gsm {
+    pub fn server(state: AppState) -> Scope {
+        web::scope("/gsm")
+            .app_data(web::Data::new(state))
+            .service(web::resource("").route(web::post().to(create_gsm_rule)))
+            .service(web::resource("/get").route(web::post().to(get_gsm_rule)))
+            .service(web::resource("/update").route(web::post().to(update_gsm_rule)))
+            .service(web::resource("/delete").route(web::post().to(delete_gsm_rule)))
+    }
+}
+
 #[cfg(all(feature = "olap", feature = "kms"))]
 pub struct Verify;
 
@@ -649,3 +729,17 @@ impl Verify {
             )
     }
 }
+
+pub struct User;
+
+#[cfg(feature = "olap")]
+impl User {
+    pub fn server(state: AppState) -> Scope {
+        web::scope("/user")
+            .app_data(web::Data::new(state))
+            .service(web::resource("/signin").route(web::post().to(user_connect_account)))
+            .service(web::resource("/signup").route(web::post().to(user_connect_account)))
+            .service(web::resource("/v2/signin").route(web::post().to(user_connect_account)))
+            .service(web::resource("/v2/signup").route(web::post().to(user_connect_account)))
+    }
+}
diff --git a/crates/router/src/routes/customers.rs b/crates/router/src/routes/customers.rs
index ff2ffc2a3fe3..cfc37cbdbb2a 100644
--- a/crates/router/src/routes/customers.rs
+++ b/crates/router/src/routes/customers.rs
@@ -30,7 +30,7 @@ pub async fn customers_create(
     json_payload: web::Json<customers::CustomerRequest>,
 ) -> HttpResponse {
     let flow = Flow::CustomersCreate;
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -38,7 +38,7 @@ pub async fn customers_create(
         |state, auth, req| create_customer(state, auth.merchant_account, auth.key_store, req),
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Retrieve Customer
@@ -142,7 +142,7 @@ pub async fn customers_update(
     let flow = Flow::CustomersUpdate;
     let customer_id = path.into_inner();
     json_payload.customer_id = customer_id;
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -150,7 +150,7 @@ pub async fn customers_update(
         |state, auth, req| update_customer(state, auth.merchant_account, req, auth.key_store),
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Delete Customer
@@ -179,7 +179,7 @@ pub async fn customers_delete(
         customer_id: path.into_inner(),
     })
     .into_inner();
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -187,7 +187,7 @@ pub async fn customers_delete(
         |state, auth, req| delete_customer(state, auth.merchant_account, req, auth.key_store),
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 #[instrument(skip_all, fields(flow = ?Flow::CustomersGetMandates))]
diff --git a/crates/router/src/routes/disputes.rs b/crates/router/src/routes/disputes.rs
index d570a5319687..aaeb118645db 100644
--- a/crates/router/src/routes/disputes.rs
+++ b/crates/router/src/routes/disputes.rs
@@ -117,7 +117,7 @@ pub async fn accept_dispute(
     let dispute_id = dispute_types::DisputeId {
         dispute_id: path.into_inner(),
     };
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -127,7 +127,7 @@ pub async fn accept_dispute(
         },
         auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Disputes - Submit Dispute Evidence
@@ -150,7 +150,7 @@ pub async fn submit_dispute_evidence(
     json_payload: web::Json<dispute_models::SubmitEvidenceRequest>,
 ) -> HttpResponse {
     let flow = Flow::DisputesEvidenceSubmit;
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -160,7 +160,7 @@ pub async fn submit_dispute_evidence(
         },
         auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Disputes - Attach Evidence to Dispute
@@ -191,7 +191,7 @@ pub async fn attach_dispute_evidence(
         Ok(valid_request) => valid_request,
         Err(err) => return api::log_and_return_error_response(err),
     };
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -201,7 +201,7 @@ pub async fn attach_dispute_evidence(
         },
         auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Diputes - Retrieve Dispute
@@ -229,7 +229,7 @@ pub async fn retrieve_dispute_evidence(
     let dispute_id = dispute_types::DisputeId {
         dispute_id: path.into_inner(),
     };
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -237,6 +237,6 @@ pub async fn retrieve_dispute_evidence(
         |state, auth, req| disputes::retrieve_dispute_evidence(state, auth.merchant_account, req),
         auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
diff --git a/crates/router/src/routes/dummy_connector.rs b/crates/router/src/routes/dummy_connector.rs
index 52a7f7f77c9a..7d2aad7e3482 100644
--- a/crates/router/src/routes/dummy_connector.rs
+++ b/crates/router/src/routes/dummy_connector.rs
@@ -10,7 +10,7 @@ use crate::{
 mod consts;
 mod core;
 mod errors;
-mod types;
+pub mod types;
 mod utils;
 
 #[instrument(skip_all, fields(flow = ?types::Flow::DummyPaymentCreate))]
diff --git a/crates/router/src/routes/files.rs b/crates/router/src/routes/files.rs
index 4a327ba0807d..bde221ebc161 100644
--- a/crates/router/src/routes/files.rs
+++ b/crates/router/src/routes/files.rs
@@ -39,7 +39,7 @@ pub async fn files_create(
         Ok(valid_request) => valid_request,
         Err(err) => return api::log_and_return_error_response(err),
     };
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -47,7 +47,7 @@ pub async fn files_create(
         |state, auth, req| files_create_core(state, auth.merchant_account, auth.key_store, req),
         auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Files - Delete
@@ -77,7 +77,7 @@ pub async fn files_delete(
     let file_id = files::FileId {
         file_id: path.into_inner(),
     };
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -85,7 +85,7 @@ pub async fn files_delete(
         |state, auth, req| files_delete_core(state, auth.merchant_account, req),
         auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Files - Retrieve
@@ -115,7 +115,7 @@ pub async fn files_retrieve(
     let file_id = files::FileId {
         file_id: path.into_inner(),
     };
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -123,6 +123,6 @@ pub async fn files_retrieve(
         |state, auth, req| files_retrieve_core(state, auth.merchant_account, auth.key_store, req),
         auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
diff --git a/crates/router/src/routes/gsm.rs b/crates/router/src/routes/gsm.rs
new file mode 100644
index 000000000000..02d943792dba
--- /dev/null
+++ b/crates/router/src/routes/gsm.rs
@@ -0,0 +1,93 @@
+use actix_web::{web, HttpRequest, Responder};
+use api_models::gsm as gsm_api_types;
+use router_env::{instrument, tracing, Flow};
+
+use super::app::AppState;
+use crate::{
+    core::{api_locking, gsm},
+    services::{api, authentication as auth},
+};
+
+#[instrument(skip_all, fields(flow = ?Flow::GsmRuleCreate))]
+pub async fn create_gsm_rule(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    json_payload: web::Json<gsm_api_types::GsmCreateRequest>,
+) -> impl Responder {
+    let payload = json_payload.into_inner();
+
+    let flow = Flow::GsmRuleCreate;
+    Box::pin(api::server_wrap(
+        flow,
+        state.clone(),
+        &req,
+        payload,
+        |state, _, payload| gsm::create_gsm_rule(state, payload),
+        &auth::AdminApiAuth,
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
+}
+
+#[instrument(skip_all, fields(flow = ?Flow::GsmRuleRetrieve))]
+pub async fn get_gsm_rule(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    json_payload: web::Json<gsm_api_types::GsmRetrieveRequest>,
+) -> impl Responder {
+    let gsm_retrieve_req = json_payload.into_inner();
+    let flow = Flow::GsmRuleRetrieve;
+    Box::pin(api::server_wrap(
+        flow,
+        state.clone(),
+        &req,
+        gsm_retrieve_req,
+        |state, _, gsm_retrieve_req| gsm::retrieve_gsm_rule(state, gsm_retrieve_req),
+        &auth::AdminApiAuth,
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
+}
+
+#[instrument(skip_all, fields(flow = ?Flow::GsmRuleUpdate))]
+pub async fn update_gsm_rule(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    json_payload: web::Json<gsm_api_types::GsmUpdateRequest>,
+) -> impl Responder {
+    let payload = json_payload.into_inner();
+
+    let flow = Flow::GsmRuleUpdate;
+    Box::pin(api::server_wrap(
+        flow,
+        state.clone(),
+        &req,
+        payload,
+        |state, _, payload| gsm::update_gsm_rule(state, payload),
+        &auth::AdminApiAuth,
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
+}
+
+#[instrument(skip_all, fields(flow = ?Flow::GsmRuleDelete))]
+pub async fn delete_gsm_rule(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    json_payload: web::Json<gsm_api_types::GsmDeleteRequest>,
+) -> impl Responder {
+    let payload = json_payload.into_inner();
+
+    let flow = Flow::GsmRuleDelete;
+
+    Box::pin(api::server_wrap(
+        flow,
+        state,
+        &req,
+        payload,
+        |state, _, payload| gsm::delete_gsm_rule(state, payload),
+        &auth::AdminApiAuth,
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
+}
diff --git a/crates/router/src/routes/lock_utils.rs b/crates/router/src/routes/lock_utils.rs
index 5be361098bcc..ae573e871627 100644
--- a/crates/router/src/routes/lock_utils.rs
+++ b/crates/router/src/routes/lock_utils.rs
@@ -22,6 +22,9 @@ pub enum ApiIdentifier {
     Verification,
     ApiKeys,
     PaymentLink,
+    Routing,
+    Gsm,
+    User,
 }
 
 impl From<Flow> for ApiIdentifier {
@@ -33,6 +36,17 @@ impl From<Flow> for ApiIdentifier {
             | Flow::MerchantsAccountDelete
             | Flow::MerchantAccountList => Self::MerchantAccount,
 
+            Flow::RoutingCreateConfig
+            | Flow::RoutingLinkConfig
+            | Flow::RoutingUnlinkConfig
+            | Flow::RoutingRetrieveConfig
+            | Flow::RoutingRetrieveActiveConfig
+            | Flow::RoutingRetrieveDefaultConfig
+            | Flow::RoutingRetrieveDictionary
+            | Flow::RoutingUpdateConfig
+            | Flow::RoutingUpdateDefaultConfig
+            | Flow::RoutingDeleteConfig => Self::Routing,
+
             Flow::MerchantConnectorsCreate
             | Flow::MerchantConnectorsRetrieve
             | Flow::MerchantConnectorsUpdate
@@ -117,6 +131,12 @@ impl From<Flow> for ApiIdentifier {
             Flow::Verification => Self::Verification,
 
             Flow::PaymentLinkInitiate | Flow::PaymentLinkRetrieve => Self::PaymentLink,
+            Flow::GsmRuleCreate
+            | Flow::GsmRuleRetrieve
+            | Flow::GsmRuleUpdate
+            | Flow::GsmRuleDelete => Self::Gsm,
+
+            Flow::UserConnectAccount => Self::User,
         }
     }
 }
diff --git a/crates/router/src/routes/metrics.rs b/crates/router/src/routes/metrics.rs
index 34d818eaa392..a8e6f9d2a892 100644
--- a/crates/router/src/routes/metrics.rs
+++ b/crates/router/src/routes/metrics.rs
@@ -102,5 +102,13 @@ counter_metric!(APPLE_PAY_SIMPLIFIED_FLOW_SUCCESSFUL_PAYMENT, GLOBAL_METER);
 counter_metric!(APPLE_PAY_MANUAL_FLOW_FAILED_PAYMENT, GLOBAL_METER);
 counter_metric!(APPLE_PAY_SIMPLIFIED_FLOW_FAILED_PAYMENT, GLOBAL_METER);
 
+// Metrics for Auto Retries
+counter_metric!(AUTO_RETRY_ELIGIBLE_REQUEST_COUNT, GLOBAL_METER);
+counter_metric!(AUTO_RETRY_GSM_MISS_COUNT, GLOBAL_METER);
+counter_metric!(AUTO_RETRY_GSM_FETCH_FAILURE_COUNT, GLOBAL_METER);
+counter_metric!(AUTO_RETRY_GSM_MATCH_COUNT, GLOBAL_METER);
+counter_metric!(AUTO_RETRY_EXHAUSTED_COUNT, GLOBAL_METER);
+counter_metric!(AUTO_RETRY_PAYMENT_COUNT, GLOBAL_METER);
+
 pub mod request;
 pub mod utils;
diff --git a/crates/router/src/routes/payment_link.rs b/crates/router/src/routes/payment_link.rs
index b664ee4429d4..7d6bf1a05f09 100644
--- a/crates/router/src/routes/payment_link.rs
+++ b/crates/router/src/routes/payment_link.rs
@@ -62,7 +62,7 @@ pub async fn initiate_payment_link(
         payment_id,
         merchant_id: merchant_id.clone(),
     };
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -77,6 +77,6 @@ pub async fn initiate_payment_link(
         },
         &crate::services::authentication::MerchantIdAuth(merchant_id),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
diff --git a/crates/router/src/routes/payment_methods.rs b/crates/router/src/routes/payment_methods.rs
index faaf757fd7e7..83d4c7f96611 100644
--- a/crates/router/src/routes/payment_methods.rs
+++ b/crates/router/src/routes/payment_methods.rs
@@ -34,7 +34,7 @@ pub async fn create_payment_method_api(
     json_payload: web::Json<payment_methods::PaymentMethodCreate>,
 ) -> HttpResponse {
     let flow = Flow::PaymentMethodsCreate;
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -44,7 +44,7 @@ pub async fn create_payment_method_api(
         },
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// List payment methods for a Merchant
@@ -84,7 +84,7 @@ pub async fn list_payment_method_api(
         Err(e) => return api::log_and_return_error_response(e),
     };
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -94,7 +94,7 @@ pub async fn list_payment_method_api(
         },
         &*auth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// List payment methods for a Customer
@@ -135,7 +135,7 @@ pub async fn list_customer_payment_method_api(
         Err(e) => return api::log_and_return_error_response(e),
     };
     let customer_id = customer_id.into_inner().0;
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -151,7 +151,7 @@ pub async fn list_customer_payment_method_api(
         },
         &*auth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// List payment methods for a Customer
@@ -191,7 +191,7 @@ pub async fn list_customer_payment_method_api_client(
         Ok((auth, _auth_flow)) => (auth, _auth_flow),
         Err(e) => return api::log_and_return_error_response(e),
     };
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -207,7 +207,7 @@ pub async fn list_customer_payment_method_api_client(
         },
         &*auth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Payment Method - Retrieve
@@ -239,7 +239,7 @@ pub async fn payment_method_retrieve_api(
     })
     .into_inner();
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -247,7 +247,7 @@ pub async fn payment_method_retrieve_api(
         |state, _auth, pm| cards::retrieve_payment_method(state, pm),
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Payment Method - Update
@@ -278,7 +278,7 @@ pub async fn payment_method_update_api(
     let flow = Flow::PaymentMethodsUpdate;
     let payment_method_id = path.into_inner();
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -294,7 +294,7 @@ pub async fn payment_method_update_api(
         },
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Payment Method - Delete
@@ -324,7 +324,7 @@ pub async fn payment_method_delete_api(
     let pm = PaymentMethodId {
         payment_method_id: payment_method_id.into_inner().0,
     };
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -332,7 +332,7 @@ pub async fn payment_method_delete_api(
         |state, auth, req| cards::delete_payment_method(state, auth.merchant_account, req),
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 #[cfg(test)]
diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs
index b760aa83aaa0..b05fae65338a 100644
--- a/crates/router/src/routes/payments.rs
+++ b/crates/router/src/routes/payments.rs
@@ -4,7 +4,7 @@ pub mod helpers;
 use actix_web::{web, Responder};
 use api_models::payments::HeaderPayload;
 use error_stack::report;
-use router_env::{instrument, tracing, types, Flow};
+use router_env::{env, instrument, tracing, types, Flow};
 
 use crate::{
     self as app,
@@ -13,12 +13,12 @@ use crate::{
         payment_methods::{Oss, PaymentMethodRetrieve},
         payments::{self, PaymentRedirectFlow},
     },
-    openapi::examples::{
-        PAYMENTS_CREATE, PAYMENTS_CREATE_MINIMUM_FIELDS, PAYMENTS_CREATE_WITH_ADDRESS,
-        PAYMENTS_CREATE_WITH_CUSTOMER_DATA, PAYMENTS_CREATE_WITH_FORCED_3DS,
-        PAYMENTS_CREATE_WITH_MANUAL_CAPTURE, PAYMENTS_CREATE_WITH_NOON_ORDER_CATETORY,
-        PAYMENTS_CREATE_WITH_ORDER_DETAILS,
-    },
+    // openapi::examples::{
+    //     PAYMENTS_CREATE, PAYMENTS_CREATE_MINIMUM_FIELDS, PAYMENTS_CREATE_WITH_ADDRESS,
+    //     PAYMENTS_CREATE_WITH_CUSTOMER_DATA, PAYMENTS_CREATE_WITH_FORCED_3DS,
+    //     PAYMENTS_CREATE_WITH_MANUAL_CAPTURE, PAYMENTS_CREATE_WITH_NOON_ORDER_CATETORY,
+    //     PAYMENTS_CREATE_WITH_ORDER_DETAILS,
+    // },
     routes::lock_utils,
     services::{api, authentication as auth},
     types::{
@@ -36,48 +36,49 @@ use crate::{
     path = "/payments",
     request_body(
         content = PaymentsCreateRequest,
-        examples(
-            (
-                "Create a payment with minimul fields" = (
-                    value = json!(PAYMENTS_CREATE_MINIMUM_FIELDS)
-                )
-            ),
-            (
-                "Create a manual capture payment" = (
-                    value = json!(PAYMENTS_CREATE_WITH_MANUAL_CAPTURE)
-                )
-            ),
-            (
-                "Create a payment with address" = (
-                    value = json!(PAYMENTS_CREATE_WITH_ADDRESS)
-                )
-            ),
-            (
-                "Create a payment with customer details" = (
-                    value = json!(PAYMENTS_CREATE_WITH_CUSTOMER_DATA)
-                )
-            ),
-            (
-                "Create a 3DS payment" = (
-                    value = json!(PAYMENTS_CREATE_WITH_FORCED_3DS)
-                )
-            ),
-            (
-                "Create a payment" = (
-                    value = json!(PAYMENTS_CREATE)
-                )
-            ),
-            (
-                "Create a payment with order details" = (
-                    value = json!(PAYMENTS_CREATE_WITH_ORDER_DETAILS)
-                )
-            ),
-            (
-                "Create a payment with order category for noon" = (
-                    value = json!(PAYMENTS_CREATE_WITH_NOON_ORDER_CATETORY)
-                )
-            ),
-        )),
+        // examples(
+        //     (
+        //         "Create a payment with minimul fields" = (
+        //             value = json!(PAYMENTS_CREATE_MINIMUM_FIELDS)
+        //         )
+        //     ),
+        //     (
+        //         "Create a manual capture payment" = (
+        //             value = json!(PAYMENTS_CREATE_WITH_MANUAL_CAPTURE)
+        //         )
+        //     ),
+        //     (
+        //         "Create a payment with address" = (
+        //             value = json!(PAYMENTS_CREATE_WITH_ADDRESS)
+        //         )
+        //     ),
+        //     (
+        //         "Create a payment with customer details" = (
+        //             value = json!(PAYMENTS_CREATE_WITH_CUSTOMER_DATA)
+        //         )
+        //     ),
+        //     (
+        //         "Create a 3DS payment" = (
+        //             value = json!(PAYMENTS_CREATE_WITH_FORCED_3DS)
+        //         )
+        //     ),
+        //     (
+        //         "Create a payment" = (
+        //             value = json!(PAYMENTS_CREATE)
+        //         )
+        //     ),
+        //     (
+        //         "Create a payment with order details" = (
+        //             value = json!(PAYMENTS_CREATE_WITH_ORDER_DETAILS)
+        //         )
+        //     ),
+        //     (
+        //         "Create a payment with order category for noon" = (
+        //             value = json!(PAYMENTS_CREATE_WITH_NOON_ORDER_CATETORY)
+        //         )
+        //     ),
+        // )
+    ),
     responses(
         (status = 200, description = "Payment created", body = PaymentsResponse),
         (status = 400, description = "Missing Mandatory fields")
@@ -101,7 +102,7 @@ pub async fn payments_create(
 
     let locking_action = payload.get_locking_input(flow.clone());
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -117,9 +118,12 @@ pub async fn payments_create(
                 api::AuthFlow::Merchant,
             )
         },
-        &auth::ApiKeyAuth,
+        match env::which() {
+            env::Env::Production => &auth::ApiKeyAuth,
+            _ => auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+        },
         locking_action,
-    )
+    ))
     .await
 }
 // /// Payments - Redirect
@@ -156,7 +160,7 @@ pub async fn payments_start(
 
     let locking_action = payload.get_locking_input(flow.clone());
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -177,12 +181,13 @@ pub async fn payments_start(
                 req,
                 api::AuthFlow::Client,
                 payments::CallConnectorAction::Trigger,
+                None,
                 HeaderPayload::default(),
             )
         },
         &auth::MerchantIdAuth(merchant_id),
         locking_action,
-    )
+    ))
     .await
 }
 /// Payments - Retrieve
@@ -229,7 +234,7 @@ pub async fn payments_retrieve(
 
     let locking_action = payload.get_locking_input(flow.clone());
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -243,12 +248,17 @@ pub async fn payments_retrieve(
                 req,
                 auth_flow,
                 payments::CallConnectorAction::Trigger,
+                None,
                 HeaderPayload::default(),
             )
         },
-        &*auth_type,
+        auth::auth_type(
+            &*auth_type,
+            &auth::JWTAuth,
+            req.headers(),
+        ),
         locking_action,
-    )
+    ))
     .await
 }
 /// Payments - Retrieve with gateway credentials
@@ -290,7 +300,7 @@ pub async fn payments_retrieve_with_gateway_creds(
 
     let locking_action = payload.get_locking_input(flow.clone());
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -304,12 +314,13 @@ pub async fn payments_retrieve_with_gateway_creds(
                 req,
                 api::AuthFlow::Merchant,
                 payments::CallConnectorAction::Trigger,
+                None,
                 HeaderPayload::default(),
             )
         },
         &*auth_type,
         locking_action,
-    )
+    ))
     .await
 }
 /// Payments - Update
@@ -356,7 +367,7 @@ pub async fn payments_update(
 
     let locking_action = payload.get_locking_input(flow.clone());
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -374,7 +385,7 @@ pub async fn payments_update(
         },
         &*auth_type,
         locking_action,
-    )
+    ))
     .await
 }
 /// Payments - Confirm
@@ -432,7 +443,7 @@ pub async fn payments_confirm(
 
     let locking_action = payload.get_locking_input(flow.clone());
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -450,7 +461,7 @@ pub async fn payments_confirm(
         },
         &*auth_type,
         locking_action,
-    )
+    ))
     .await
 }
 /// Payments - Capture
@@ -487,7 +498,7 @@ pub async fn payments_capture(
 
     let locking_action = payload.get_locking_input(flow.clone());
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -508,12 +519,13 @@ pub async fn payments_capture(
                 payload,
                 api::AuthFlow::Merchant,
                 payments::CallConnectorAction::Trigger,
+                None,
                 HeaderPayload::default(),
             )
         },
         &auth::ApiKeyAuth,
         locking_action,
-    )
+    ))
     .await
 }
 /// Payments - Session token
@@ -542,7 +554,7 @@ pub async fn payments_connector_session(
 
     let locking_action = payload.get_locking_input(flow.clone());
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -563,12 +575,13 @@ pub async fn payments_connector_session(
                 payload,
                 api::AuthFlow::Client,
                 payments::CallConnectorAction::Trigger,
+                None,
                 HeaderPayload::default(),
             )
         },
         &auth::PublishableKeyAuth,
         locking_action,
-    )
+    ))
     .await
 }
 // /// Payments - Redirect response
@@ -759,7 +772,7 @@ pub async fn payments_cancel(
     let payment_id = path.into_inner();
     payload.payment_id = payment_id;
     let locking_action = payload.get_locking_input(flow.clone());
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -773,12 +786,13 @@ pub async fn payments_cancel(
                 req,
                 api::AuthFlow::Merchant,
                 payments::CallConnectorAction::Trigger,
+                None,
                 HeaderPayload::default(),
             )
         },
         &auth::ApiKeyAuth,
         locking_action,
-    )
+    ))
     .await
 }
 /// Payments - List
@@ -821,7 +835,7 @@ pub async fn payments_list(
         &req,
         payload,
         |state, auth, req| payments::list_payments(state, auth.merchant_account, req),
-        &auth::ApiKeyAuth,
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
     )
     .await
@@ -841,7 +855,7 @@ pub async fn payments_list_by_filter(
         &req,
         payload,
         |state, auth, req| payments::apply_filters_on_payments(state, auth.merchant_account, req),
-        &auth::ApiKeyAuth,
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
     )
     .await
@@ -861,7 +875,7 @@ pub async fn get_filters_for_payments(
         &req,
         payload,
         |state, auth, req| payments::get_filters_for_payments(state, auth.merchant_account, req),
-        &auth::ApiKeyAuth,
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
     )
     .await
@@ -896,6 +910,7 @@ where
     // the operation are flow agnostic, and the flow is only required in the post_update_tracker
     // Thus the flow can be generated just before calling the connector instead of explicitly passing it here.
 
+    let eligible_connectors = req.connector.clone();
     match req.payment_type.unwrap_or_default() {
         api_models::enums::PaymentType::Normal
         | api_models::enums::PaymentType::RecurringMandate
@@ -915,6 +930,7 @@ where
                 req,
                 auth_flow,
                 payments::CallConnectorAction::Trigger,
+                eligible_connectors,
                 header_payload,
             )
             .await
@@ -935,6 +951,7 @@ where
                 req,
                 auth_flow,
                 payments::CallConnectorAction::Trigger,
+                eligible_connectors,
                 header_payload,
             )
             .await
diff --git a/crates/router/src/routes/payouts.rs b/crates/router/src/routes/payouts.rs
index 15cf59aaf32d..cc47263a0c56 100644
--- a/crates/router/src/routes/payouts.rs
+++ b/crates/router/src/routes/payouts.rs
@@ -33,7 +33,7 @@ pub async fn payouts_create(
     json_payload: web::Json<payout_types::PayoutCreateRequest>,
 ) -> HttpResponse {
     let flow = Flow::PayoutsCreate;
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -41,7 +41,7 @@ pub async fn payouts_create(
         |state, auth, req| payouts_create_core(state, auth.merchant_account, auth.key_store, req),
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Payouts - Retrieve
@@ -72,7 +72,7 @@ pub async fn payouts_retrieve(
         force_sync: query_params.force_sync,
     };
     let flow = Flow::PayoutsRetrieve;
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -80,7 +80,7 @@ pub async fn payouts_retrieve(
         |state, auth, req| payouts_retrieve_core(state, auth.merchant_account, auth.key_store, req),
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Payouts - Update
@@ -111,7 +111,7 @@ pub async fn payouts_update(
     let payout_id = path.into_inner();
     let mut payout_update_payload = json_payload.into_inner();
     payout_update_payload.payout_id = Some(payout_id);
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -119,7 +119,7 @@ pub async fn payouts_update(
         |state, auth, req| payouts_update_core(state, auth.merchant_account, auth.key_store, req),
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Payouts - Cancel
@@ -150,7 +150,7 @@ pub async fn payouts_cancel(
     let mut payload = json_payload.into_inner();
     payload.payout_id = path.into_inner();
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -158,7 +158,7 @@ pub async fn payouts_cancel(
         |state, auth, req| payouts_cancel_core(state, auth.merchant_account, auth.key_store, req),
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Payouts - Fulfill
@@ -189,7 +189,7 @@ pub async fn payouts_fulfill(
     let mut payload = json_payload.into_inner();
     payload.payout_id = path.into_inner();
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -197,7 +197,7 @@ pub async fn payouts_fulfill(
         |state, auth, req| payouts_fulfill_core(state, auth.merchant_account, auth.key_store, req),
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 #[instrument(skip_all, fields(flow = ?Flow::PayoutsAccounts))]
diff --git a/crates/router/src/routes/refunds.rs b/crates/router/src/routes/refunds.rs
index 4c4121b5d532..d370af6b8d7a 100644
--- a/crates/router/src/routes/refunds.rs
+++ b/crates/router/src/routes/refunds.rs
@@ -31,15 +31,15 @@ pub async fn refunds_create(
     json_payload: web::Json<refunds::RefundRequest>,
 ) -> HttpResponse {
     let flow = Flow::RefundsCreate;
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
         json_payload.into_inner(),
         |state, auth, req| refund_create_core(state, auth.merchant_account, auth.key_store, req),
-        &auth::ApiKeyAuth,
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Refunds - Retrieve (GET)
@@ -74,7 +74,7 @@ pub async fn refunds_retrieve(
     };
     let flow = Flow::RefundsRetrieve;
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -88,9 +88,9 @@ pub async fn refunds_retrieve(
                 refund_retrieve_core,
             )
         },
-        &auth::ApiKeyAuth,
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Refunds - Retrieve (POST)
@@ -115,7 +115,7 @@ pub async fn refunds_retrieve_with_body(
     json_payload: web::Json<refunds::RefundsRetrieveRequest>,
 ) -> HttpResponse {
     let flow = Flow::RefundsRetrieve;
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -131,7 +131,7 @@ pub async fn refunds_retrieve_with_body(
         },
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 /// Refunds - Update
@@ -161,13 +161,14 @@ pub async fn refunds_update(
     path: web::Path<String>,
 ) -> HttpResponse {
     let flow = Flow::RefundsUpdate;
-    let refund_id = path.into_inner();
+    let mut refund_update_req = json_payload.into_inner();
+    refund_update_req.refund_id = path.into_inner();
     api::server_wrap(
         flow,
         state,
         &req,
-        json_payload.into_inner(),
-        |state, auth, req| refund_update_core(state, auth.merchant_account, &refund_id, req),
+        refund_update_req,
+        |state, auth, req| refund_update_core(state, auth.merchant_account, req),
         &auth::ApiKeyAuth,
         api_locking::LockAction::NotApplicable,
     )
@@ -201,7 +202,7 @@ pub async fn refunds_list(
         &req,
         payload.into_inner(),
         |state, auth, req| refund_list(state, auth.merchant_account, req),
-        &auth::ApiKeyAuth,
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
     )
     .await
@@ -225,7 +226,7 @@ pub async fn refunds_list(
 pub async fn refunds_filter_list(
     state: web::Data<AppState>,
     req: HttpRequest,
-    payload: web::Json<api_models::refunds::TimeRange>,
+    payload: web::Json<api_models::payments::TimeRange>,
 ) -> HttpResponse {
     let flow = Flow::RefundsList;
     api::server_wrap(
@@ -234,7 +235,7 @@ pub async fn refunds_filter_list(
         &req,
         payload.into_inner(),
         |state, auth, req| refund_filter_list(state, auth.merchant_account, req),
-        &auth::ApiKeyAuth,
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
     )
     .await
diff --git a/crates/router/src/routes/routing.rs b/crates/router/src/routes/routing.rs
new file mode 100644
index 000000000000..606111a88818
--- /dev/null
+++ b/crates/router/src/routes/routing.rs
@@ -0,0 +1,355 @@
+//! Analysis for usage of Routing in Payment flows
+//!
+//! Functions that are used to perform the api level configuration, retrieval, updation
+//! of Routing configs.
+use actix_web::{web, HttpRequest, Responder};
+use api_models::routing as routing_types;
+#[cfg(feature = "business_profile_routing")]
+use api_models::routing::{RoutingRetrieveLinkQuery, RoutingRetrieveQuery};
+use router_env::{
+    tracing::{self, instrument},
+    Flow,
+};
+
+use crate::{
+    core::{api_locking, routing},
+    routes::AppState,
+    services::{api as oss_api, authentication as auth},
+};
+
+#[cfg(feature = "olap")]
+#[instrument(skip_all)]
+pub async fn routing_create_config(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    json_payload: web::Json<routing_types::RoutingConfigRequest>,
+) -> impl Responder {
+    let flow = Flow::RoutingCreateConfig;
+    Box::pin(oss_api::server_wrap(
+        flow,
+        state,
+        &req,
+        json_payload.into_inner(),
+        |state, auth: auth::AuthenticationData, payload| {
+            routing::create_routing_config(state, auth.merchant_account, auth.key_store, payload)
+        },
+        #[cfg(not(feature = "release"))]
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+        #[cfg(feature = "release")]
+        &auth::JWTAuth,
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
+}
+
+#[cfg(feature = "olap")]
+#[instrument(skip_all)]
+pub async fn routing_link_config(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    path: web::Path<routing_types::RoutingAlgorithmId>,
+) -> impl Responder {
+    let flow = Flow::RoutingLinkConfig;
+    Box::pin(oss_api::server_wrap(
+        flow,
+        state,
+        &req,
+        path.into_inner(),
+        |state, auth: auth::AuthenticationData, algorithm_id| {
+            routing::link_routing_config(
+                state,
+                auth.merchant_account,
+                #[cfg(not(feature = "business_profile_routing"))]
+                auth.key_store,
+                algorithm_id.0,
+            )
+        },
+        #[cfg(not(feature = "release"))]
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+        #[cfg(feature = "release")]
+        &auth::JWTAuth,
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
+}
+
+#[cfg(feature = "olap")]
+#[instrument(skip_all)]
+pub async fn routing_retrieve_config(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    path: web::Path<routing_types::RoutingAlgorithmId>,
+) -> impl Responder {
+    let algorithm_id = path.into_inner();
+    let flow = Flow::RoutingRetrieveConfig;
+    Box::pin(oss_api::server_wrap(
+        flow,
+        state,
+        &req,
+        algorithm_id,
+        |state, auth: auth::AuthenticationData, algorithm_id| {
+            routing::retrieve_routing_config(state, auth.merchant_account, algorithm_id)
+        },
+        #[cfg(not(feature = "release"))]
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+        #[cfg(feature = "release")]
+        &auth::JWTAuth,
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
+}
+
+#[cfg(feature = "olap")]
+#[instrument(skip_all)]
+pub async fn routing_retrieve_dictionary(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    #[cfg(feature = "business_profile_routing")] query: web::Query<RoutingRetrieveQuery>,
+) -> impl Responder {
+    #[cfg(feature = "business_profile_routing")]
+    {
+        let flow = Flow::RoutingRetrieveDictionary;
+        Box::pin(oss_api::server_wrap(
+            flow,
+            state,
+            &req,
+            query.into_inner(),
+            |state, auth: auth::AuthenticationData, query_params| {
+                routing::retrieve_merchant_routing_dictionary(
+                    state,
+                    auth.merchant_account,
+                    query_params,
+                )
+            },
+            #[cfg(not(feature = "release"))]
+            auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+            #[cfg(feature = "release")]
+            &auth::JWTAuth,
+            api_locking::LockAction::NotApplicable,
+        ))
+        .await
+    }
+
+    #[cfg(not(feature = "business_profile_routing"))]
+    {
+        let flow = Flow::RoutingRetrieveDictionary;
+        Box::pin(oss_api::server_wrap(
+            flow,
+            state,
+            &req,
+            (),
+            |state, auth: auth::AuthenticationData, _| {
+                routing::retrieve_merchant_routing_dictionary(state, auth.merchant_account)
+            },
+            #[cfg(not(feature = "release"))]
+            auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+            #[cfg(feature = "release")]
+            &auth::JWTAuth,
+            api_locking::LockAction::NotApplicable,
+        ))
+        .await
+    }
+}
+
+#[cfg(feature = "olap")]
+#[instrument(skip_all)]
+pub async fn routing_unlink_config(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    #[cfg(feature = "business_profile_routing")] payload: web::Json<
+        routing_types::RoutingConfigRequest,
+    >,
+) -> impl Responder {
+    #[cfg(feature = "business_profile_routing")]
+    {
+        let flow = Flow::RoutingUnlinkConfig;
+        Box::pin(oss_api::server_wrap(
+            flow,
+            state,
+            &req,
+            payload.into_inner(),
+            |state, auth: auth::AuthenticationData, payload_req| {
+                routing::unlink_routing_config(state, auth.merchant_account, payload_req)
+            },
+            #[cfg(not(feature = "release"))]
+            auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+            #[cfg(feature = "release")]
+            &auth::JWTAuth,
+            api_locking::LockAction::NotApplicable,
+        ))
+        .await
+    }
+
+    #[cfg(not(feature = "business_profile_routing"))]
+    {
+        let flow = Flow::RoutingUnlinkConfig;
+        Box::pin(oss_api::server_wrap(
+            flow,
+            state,
+            &req,
+            (),
+            |state, auth: auth::AuthenticationData, _| {
+                routing::unlink_routing_config(state, auth.merchant_account, auth.key_store)
+            },
+            #[cfg(not(feature = "release"))]
+            auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+            #[cfg(feature = "release")]
+            &auth::JWTAuth,
+            api_locking::LockAction::NotApplicable,
+        ))
+        .await
+    }
+}
+
+#[cfg(feature = "olap")]
+#[instrument(skip_all)]
+pub async fn routing_update_default_config(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    json_payload: web::Json<Vec<routing_types::RoutableConnectorChoice>>,
+) -> impl Responder {
+    oss_api::server_wrap(
+        Flow::RoutingUpdateDefaultConfig,
+        state,
+        &req,
+        json_payload.into_inner(),
+        |state, auth: auth::AuthenticationData, updated_config| {
+            routing::update_default_routing_config(state, auth.merchant_account, updated_config)
+        },
+        #[cfg(not(feature = "release"))]
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+        #[cfg(feature = "release")]
+        &auth::JWTAuth,
+        api_locking::LockAction::NotApplicable,
+    )
+    .await
+}
+
+#[cfg(feature = "olap")]
+#[instrument(skip_all)]
+pub async fn routing_retrieve_default_config(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+) -> impl Responder {
+    oss_api::server_wrap(
+        Flow::RoutingRetrieveDefaultConfig,
+        state,
+        &req,
+        (),
+        |state, auth: auth::AuthenticationData, _| {
+            routing::retrieve_default_routing_config(state, auth.merchant_account)
+        },
+        #[cfg(not(feature = "release"))]
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+        #[cfg(feature = "release")]
+        &auth::JWTAuth,
+        api_locking::LockAction::NotApplicable,
+    )
+    .await
+}
+
+#[cfg(feature = "olap")]
+#[instrument(skip_all)]
+pub async fn routing_retrieve_linked_config(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    #[cfg(feature = "business_profile_routing")] query: web::Query<RoutingRetrieveLinkQuery>,
+) -> impl Responder {
+    #[cfg(feature = "business_profile_routing")]
+    {
+        use crate::services::authentication::AuthenticationData;
+        let flow = Flow::RoutingRetrieveActiveConfig;
+        Box::pin(oss_api::server_wrap(
+            flow,
+            state,
+            &req,
+            query.into_inner(),
+            |state, auth: AuthenticationData, query_params| {
+                routing::retrieve_linked_routing_config(state, auth.merchant_account, query_params)
+            },
+            #[cfg(not(feature = "release"))]
+            auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+            #[cfg(feature = "release")]
+            &auth::JWTAuth,
+            api_locking::LockAction::NotApplicable,
+        ))
+        .await
+    }
+
+    #[cfg(not(feature = "business_profile_routing"))]
+    {
+        let flow = Flow::RoutingRetrieveActiveConfig;
+        Box::pin(oss_api::server_wrap(
+            flow,
+            state,
+            &req,
+            (),
+            |state, auth: auth::AuthenticationData, _| {
+                routing::retrieve_linked_routing_config(state, auth.merchant_account)
+            },
+            #[cfg(not(feature = "release"))]
+            auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+            #[cfg(feature = "release")]
+            &auth::JWTAuth,
+            api_locking::LockAction::NotApplicable,
+        ))
+        .await
+    }
+}
+
+#[cfg(feature = "olap")]
+#[instrument(skip_all)]
+pub async fn routing_retrieve_default_config_for_profiles(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+) -> impl Responder {
+    oss_api::server_wrap(
+        Flow::RoutingRetrieveDefaultConfig,
+        state,
+        &req,
+        (),
+        |state, auth: auth::AuthenticationData, _| {
+            routing::retrieve_default_routing_config_for_profiles(state, auth.merchant_account)
+        },
+        #[cfg(not(feature = "release"))]
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+        #[cfg(feature = "release")]
+        &auth::JWTAuth,
+        api_locking::LockAction::NotApplicable,
+    )
+    .await
+}
+
+#[cfg(feature = "olap")]
+#[instrument(skip_all)]
+pub async fn routing_update_default_config_for_profile(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    path: web::Path<String>,
+    json_payload: web::Json<Vec<routing_types::RoutableConnectorChoice>>,
+) -> impl Responder {
+    let routing_payload_wrapper = routing_types::RoutingPayloadWrapper {
+        updated_config: json_payload.into_inner(),
+        profile_id: path.into_inner(),
+    };
+    oss_api::server_wrap(
+        Flow::RoutingUpdateDefaultConfig,
+        state,
+        &req,
+        routing_payload_wrapper,
+        |state, auth: auth::AuthenticationData, wrapper| {
+            routing::update_default_routing_config_for_profile(
+                state,
+                auth.merchant_account,
+                wrapper.updated_config,
+                wrapper.profile_id,
+            )
+        },
+        #[cfg(not(feature = "release"))]
+        auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
+        #[cfg(feature = "release")]
+        &auth::JWTAuth,
+        api_locking::LockAction::NotApplicable,
+    )
+    .await
+}
diff --git a/crates/router/src/routes/user.rs b/crates/router/src/routes/user.rs
new file mode 100644
index 000000000000..0ff11ce087b5
--- /dev/null
+++ b/crates/router/src/routes/user.rs
@@ -0,0 +1,31 @@
+use actix_web::{web, HttpRequest, HttpResponse};
+use api_models::user as user_api;
+use router_env::Flow;
+
+use super::AppState;
+use crate::{
+    core::{api_locking, user},
+    services::{
+        api,
+        authentication::{self as auth},
+    },
+};
+
+pub async fn user_connect_account(
+    state: web::Data<AppState>,
+    http_req: HttpRequest,
+    json_payload: web::Json<user_api::ConnectAccountRequest>,
+) -> HttpResponse {
+    let flow = Flow::UserConnectAccount;
+    let req_payload = json_payload.into_inner();
+    Box::pin(api::server_wrap(
+        flow.clone(),
+        state,
+        &http_req,
+        req_payload.clone(),
+        |state, _, req_body| user::connect_account(state, req_body),
+        &auth::NoAuth,
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
+}
diff --git a/crates/router/src/routes/verification.rs b/crates/router/src/routes/verification.rs
index a0861f2b14d7..d0525bb272e8 100644
--- a/crates/router/src/routes/verification.rs
+++ b/crates/router/src/routes/verification.rs
@@ -18,11 +18,11 @@ pub async fn apple_pay_merchant_registration(
     let flow = Flow::Verification;
     let merchant_id = path.into_inner();
     let kms_conf = &state.clone().conf.kms;
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
-        json_payload,
+        json_payload.into_inner(),
         |state, _, body| {
             verification::verify_merchant_creds_for_applepay(
                 state.clone(),
@@ -34,7 +34,7 @@ pub async fn apple_pay_merchant_registration(
         },
         auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
 
diff --git a/crates/router/src/routes/webhooks.rs b/crates/router/src/routes/webhooks.rs
index f9fee54d16f1..63f2328ec6ce 100644
--- a/crates/router/src/routes/webhooks.rs
+++ b/crates/router/src/routes/webhooks.rs
@@ -21,23 +21,23 @@ pub async fn receive_incoming_webhook<W: types::OutgoingWebhookType>(
     let flow = Flow::IncomingWebhookReceive;
     let (merchant_id, connector_id_or_name) = path.into_inner();
 
-    api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
-        body,
-        |state, auth, body| {
+        (),
+        |state, auth, _| {
             webhooks::webhooks_wrapper::<W, Oss>(
                 state.to_owned(),
                 &req,
                 auth.merchant_account,
                 auth.key_store,
                 &connector_id_or_name,
-                body,
+                body.clone(),
             )
         },
         &auth::MerchantIdAuth(merchant_id),
         api_locking::LockAction::NotApplicable,
-    )
+    ))
     .await
 }
diff --git a/crates/router/src/services.rs b/crates/router/src/services.rs
index d216d6164276..21f33f0fa0b8 100644
--- a/crates/router/src/services.rs
+++ b/crates/router/src/services.rs
@@ -1,6 +1,8 @@
 pub mod api;
 pub mod authentication;
 pub mod encryption;
+#[cfg(feature = "olap")]
+pub mod jwt;
 pub mod logger;
 
 #[cfg(feature = "kms")]
@@ -90,6 +92,7 @@ pub async fn get_store(
         store,
         config.drainer.stream_name.clone(),
         config.drainer.num_partitions,
+        config.kv_config.ttl,
     );
 
     Ok(store)
diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs
index b2cb29bbd2c3..0a8b84ffd11c 100644
--- a/crates/router/src/services/api.rs
+++ b/crates/router/src/services/api.rs
@@ -25,7 +25,7 @@ use serde_json::json;
 use tera::{Context, Tera};
 
 use self::request::{HeaderExt, RequestBuilderExt};
-use super::authentication::{AuthInfo, AuthenticateAndFetch};
+use super::authentication::AuthenticateAndFetch;
 use crate::{
     configs::settings::{Connectors, Settings},
     consts,
@@ -34,7 +34,7 @@ use crate::{
         errors::{self, CustomResult},
         payments,
     },
-    events::api_logs::ApiEvent,
+    events::api_logs::{ApiEvent, ApiEventMetric, ApiEventsType},
     logger,
     routes::{
         app::AppStateInfo,
@@ -98,11 +98,7 @@ pub trait ConnectorValidation: ConnectorCommon {
     }
 
     fn validate_if_surcharge_implemented(&self) -> CustomResult<(), errors::ConnectorError> {
-        Err(errors::ConnectorError::NotImplemented(format!(
-            "Surcharge not implemented for {}",
-            self.id()
-        ))
-        .into())
+        Err(errors::ConnectorError::NotImplemented(format!("Surcharge for {}", self.id())).into())
     }
 }
 
@@ -136,6 +132,7 @@ pub trait ConnectorIntegration<T, Req, Resp>: ConnectorIntegrationAny<T, Req, Re
     fn get_request_body(
         &self,
         _req: &types::RouterData<T, Req, Resp>,
+        _connectors: &Connectors,
     ) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
         Ok(None)
     }
@@ -226,6 +223,7 @@ pub trait ConnectorIntegration<T, Req, Resp>: ConnectorIntegrationAny<T, Req, Re
             message: error_message.to_string(),
             reason: String::from_utf8(res.response.to_vec()).ok(),
             status_code: res.status_code,
+            attempt_status: None,
         })
     }
 
@@ -303,6 +301,7 @@ where
                     message: error_message.unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
                     status_code: 200, // This status code is ignored in redirection response it will override with 302 status code.
                     reason: None,
+                    attempt_status: None,
                 })
             } else {
                 None
@@ -403,7 +402,14 @@ where
                                         500..=511 => {
                                             connector_integration.get_5xx_error_response(body)?
                                         }
-                                        _ => connector_integration.get_error_response(body)?,
+                                        _ => {
+                                            let error_res =
+                                                connector_integration.get_error_response(body)?;
+                                            if let Some(status) = error_res.attempt_status {
+                                                router_data.status = status;
+                                            };
+                                            error_res
+                                        }
                                     };
 
                                     router_data.response = Err(error);
@@ -420,6 +426,7 @@ where
                                     message: consts::REQUEST_TIMEOUT_ERROR_MESSAGE.to_string(),
                                     reason: Some(consts::REQUEST_TIMEOUT_ERROR_MESSAGE.to_string()),
                                     status_code: 504,
+                                    attempt_status: None,
                                 };
                                 router_data.response = Err(error_response);
                                 router_data.connector_http_status_code = Some(504);
@@ -758,10 +765,9 @@ where
     F: Fn(A, U, T) -> Fut,
     'b: 'a,
     Fut: Future<Output = CustomResult<ApplicationResponse<Q>, E>>,
-    Q: Serialize + Debug + 'a,
-    T: Debug,
+    Q: Serialize + Debug + 'a + ApiEventMetric,
+    T: Debug + Serialize + ApiEventMetric,
     A: AppStateInfo + Clone,
-    U: AuthInfo,
     E: ErrorSwitch<OErr> + error_stack::Context,
     OErr: ResponseError + error_stack::Context,
     errors::ApiErrorResponse: ErrorSwitch<OErr>,
@@ -776,13 +782,20 @@ where
 
     request_state.add_request_id(request_id);
     let start_instant = Instant::now();
+    let serialized_request = masking::masked_serialize(&payload)
+        .into_report()
+        .attach_printable("Failed to serialize json request")
+        .change_context(errors::ApiErrorResponse::InternalServerError.switch())?;
+
+    let mut event_type = payload.get_api_event_type();
 
-    let auth_out = api_auth
+    // Currently auth failures are not recorded as API events
+    let (auth_out, auth_type) = api_auth
         .authenticate_and_fetch(request.headers(), &request_state)
         .await
         .switch()?;
 
-    let merchant_id = auth_out
+    let merchant_id = auth_type
         .get_merchant_id()
         .unwrap_or("MERCHANT_ID_NOT_FOUND")
         .to_string();
@@ -812,11 +825,50 @@ where
         .saturating_duration_since(start_instant)
         .as_millis();
 
+    let mut serialized_response = None;
+    let mut overhead_latency = None;
     let status_code = match output.as_ref() {
-        Ok(res) => metrics::request::track_response_status_code(res),
+        Ok(res) => {
+            if let ApplicationResponse::Json(data) = res {
+                serialized_response.replace(
+                    masking::masked_serialize(&data)
+                        .into_report()
+                        .attach_printable("Failed to serialize json response")
+                        .change_context(errors::ApiErrorResponse::InternalServerError.switch())?,
+                );
+            } else if let ApplicationResponse::JsonWithHeaders((data, headers)) = res {
+                serialized_response.replace(
+                    masking::masked_serialize(&data)
+                        .into_report()
+                        .attach_printable("Failed to serialize json response")
+                        .change_context(errors::ApiErrorResponse::InternalServerError.switch())?,
+                );
+
+                if let Some((_, value)) = headers.iter().find(|(key, _)| key == X_HS_LATENCY) {
+                    if let Ok(external_latency) = value.parse::<u128>() {
+                        overhead_latency.replace(external_latency);
+                    }
+                }
+            }
+            event_type = res.get_api_event_type().or(event_type);
+
+            metrics::request::track_response_status_code(res)
+        }
         Err(err) => err.current_context().status_code().as_u16().into(),
     };
-    let api_event = ApiEvent::new(flow, &request_id, request_duration, status_code);
+
+    let api_event = ApiEvent::new(
+        flow,
+        &request_id,
+        request_duration,
+        status_code,
+        serialized_request,
+        serialized_response,
+        overhead_latency,
+        auth_type,
+        event_type.unwrap_or(ApiEventsType::Miscellaneous),
+        request,
+    );
     match api_event.clone().try_into() {
         Ok(event) => {
             state.event_handler().log_event(event);
@@ -847,9 +899,8 @@ pub async fn server_wrap<'a, A, T, U, Q, F, Fut, E>(
 where
     F: Fn(A, U, T) -> Fut,
     Fut: Future<Output = CustomResult<ApplicationResponse<Q>, E>>,
-    Q: Serialize + Debug + 'a,
-    T: Debug,
-    U: AuthInfo,
+    Q: Serialize + Debug + ApiEventMetric + 'a,
+    T: Debug + Serialize + ApiEventMetric,
     A: AppStateInfo + Clone,
     ApplicationResponse<Q>: Debug,
     E: ErrorSwitch<api_models::errors::types::ApiErrorResponse> + error_stack::Context,
diff --git a/crates/router/src/services/api/client.rs b/crates/router/src/services/api/client.rs
index c47a28da0844..8eb6ab72f988 100644
--- a/crates/router/src/services/api/client.rs
+++ b/crates/router/src/services/api/client.rs
@@ -110,6 +110,7 @@ pub(super) fn create_client(
 
 pub fn proxy_bypass_urls(locker: &Locker) -> Vec<String> {
     let locker_host = locker.host.to_owned();
+    let basilisk_host = locker.basilisk_host.to_owned();
     vec![
         format!("{locker_host}/cards/add"),
         format!("{locker_host}/cards/retrieve"),
@@ -117,6 +118,10 @@ pub fn proxy_bypass_urls(locker: &Locker) -> Vec<String> {
         format!("{locker_host}/card/addCard"),
         format!("{locker_host}/card/getCard"),
         format!("{locker_host}/card/deleteCard"),
+        format!("{basilisk_host}/tokenize"),
+        format!("{basilisk_host}/tokenize/get"),
+        format!("{basilisk_host}/tokenize/delete"),
+        format!("{basilisk_host}/tokenize/delete/token"),
     ]
 }
 
diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs
index eec872a9f34f..da4dec2eec8a 100644
--- a/crates/router/src/services/authentication.rs
+++ b/crates/router/src/services/authentication.rs
@@ -7,7 +7,12 @@ use error_stack::{report, IntoReport, ResultExt};
 use external_services::kms::{self, decrypt::KmsDecrypt};
 use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
 use masking::{PeekInterface, StrongSecret};
+use serde::Serialize;
 
+#[cfg(feature = "olap")]
+use super::jwt;
+#[cfg(feature = "olap")]
+use crate::consts;
 use crate::{
     configs::settings,
     core::{
@@ -21,11 +26,86 @@ use crate::{
     utils::OptionExt,
 };
 
+#[derive(Clone, Debug)]
 pub struct AuthenticationData {
     pub merchant_account: domain::MerchantAccount,
     pub key_store: domain::MerchantKeyStore,
 }
 
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
+#[serde(
+    tag = "api_auth_type",
+    content = "authentication_data",
+    rename_all = "snake_case"
+)]
+pub enum AuthenticationType {
+    ApiKey {
+        merchant_id: String,
+        key_id: String,
+    },
+    AdminApiKey,
+    MerchantJWT {
+        merchant_id: String,
+        user_id: Option<String>,
+    },
+    MerchantID {
+        merchant_id: String,
+    },
+    PublishableKey {
+        merchant_id: String,
+    },
+    NoAuth,
+}
+
+impl AuthenticationType {
+    pub fn get_merchant_id(&self) -> Option<&str> {
+        match self {
+            Self::ApiKey {
+                merchant_id,
+                key_id: _,
+            }
+            | Self::MerchantID { merchant_id }
+            | Self::PublishableKey { merchant_id }
+            | Self::MerchantJWT {
+                merchant_id,
+                user_id: _,
+            } => Some(merchant_id.as_ref()),
+            Self::AdminApiKey | Self::NoAuth => None,
+        }
+    }
+}
+
+#[derive(serde::Serialize, serde::Deserialize)]
+pub struct AuthToken {
+    pub user_id: String,
+    pub merchant_id: String,
+    pub role_id: String,
+    pub exp: u64,
+    pub org_id: String,
+}
+
+#[cfg(feature = "olap")]
+impl AuthToken {
+    pub async fn new_token(
+        user_id: String,
+        merchant_id: String,
+        role_id: String,
+        settings: &settings::Settings,
+        org_id: String,
+    ) -> errors::UserResult<String> {
+        let exp_duration = std::time::Duration::from_secs(consts::JWT_TOKEN_TIME_IN_SECS);
+        let exp = jwt::generate_exp(exp_duration)?.as_secs();
+        let token_payload = Self {
+            user_id,
+            merchant_id,
+            role_id,
+            exp,
+            org_id,
+        };
+        jwt::generate_jwt(&token_payload, settings).await
+    }
+}
+
 pub trait AuthInfo {
     fn get_merchant_id(&self) -> Option<&str>;
 }
@@ -46,13 +126,12 @@ impl AuthInfo for AuthenticationData {
 pub trait AuthenticateAndFetch<T, A>
 where
     A: AppStateInfo,
-    T: AuthInfo,
 {
     async fn authenticate_and_fetch(
         &self,
         request_headers: &HeaderMap,
         state: &A,
-    ) -> RouterResult<T>;
+    ) -> RouterResult<(T, AuthenticationType)>;
 }
 
 #[derive(Debug)]
@@ -69,8 +148,8 @@ where
         &self,
         _request_headers: &HeaderMap,
         _state: &A,
-    ) -> RouterResult<()> {
-        Ok(())
+    ) -> RouterResult<((), AuthenticationType)> {
+        Ok(((), AuthenticationType::NoAuth))
     }
 }
 
@@ -83,7 +162,7 @@ where
         &self,
         request_headers: &HeaderMap,
         state: &A,
-    ) -> RouterResult<AuthenticationData> {
+    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
         let api_key = get_api_key(request_headers)
             .change_context(errors::ApiErrorResponse::Unauthorized)?
             .trim();
@@ -139,10 +218,17 @@ where
             .await
             .to_not_found_response(errors::ApiErrorResponse::Unauthorized)?;
 
-        Ok(AuthenticationData {
+        let auth = AuthenticationData {
             merchant_account: merchant,
             key_store,
-        })
+        };
+        Ok((
+            auth.clone(),
+            AuthenticationType::ApiKey {
+                merchant_id: auth.merchant_account.merchant_id.clone(),
+                key_id: stored_api_key.key_id,
+            },
+        ))
     }
 }
 
@@ -183,7 +269,7 @@ where
         &self,
         request_headers: &HeaderMap,
         state: &A,
-    ) -> RouterResult<()> {
+    ) -> RouterResult<((), AuthenticationType)> {
         let request_admin_api_key =
             get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?;
         let conf = state.conf();
@@ -200,7 +286,7 @@ where
                 .attach_printable("Admin Authentication Failure"))?;
         }
 
-        Ok(())
+        Ok(((), AuthenticationType::AdminApiKey))
     }
 }
 
@@ -216,7 +302,7 @@ where
         &self,
         _request_headers: &HeaderMap,
         state: &A,
-    ) -> RouterResult<AuthenticationData> {
+    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
         let key_store = state
             .store()
             .get_merchant_key_store_by_merchant_id(
@@ -245,10 +331,16 @@ where
                 }
             })?;
 
-        Ok(AuthenticationData {
+        let auth = AuthenticationData {
             merchant_account: merchant,
             key_store,
-        })
+        };
+        Ok((
+            auth.clone(),
+            AuthenticationType::MerchantID {
+                merchant_id: auth.merchant_account.merchant_id.clone(),
+            },
+        ))
     }
 }
 
@@ -264,7 +356,7 @@ where
         &self,
         request_headers: &HeaderMap,
         state: &A,
-    ) -> RouterResult<AuthenticationData> {
+    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
         let publishable_key =
             get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?;
 
@@ -279,6 +371,14 @@ where
                     e.change_context(errors::ApiErrorResponse::InternalServerError)
                 }
             })
+            .map(|auth| {
+                (
+                    auth.clone(),
+                    AuthenticationType::PublishableKey {
+                        merchant_id: auth.merchant_account.merchant_id.clone(),
+                    },
+                )
+            })
     }
 }
 
@@ -300,15 +400,59 @@ where
         &self,
         request_headers: &HeaderMap,
         state: &A,
-    ) -> RouterResult<()> {
-        let mut token = get_jwt(request_headers)?;
-        token = strip_jwt_token(token)?;
-        decode_jwt::<JwtAuthPayloadFetchUnit>(token, state)
-            .await
-            .map(|_| ())
+    ) -> RouterResult<((), AuthenticationType)> {
+        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
+        Ok((
+            (),
+            AuthenticationType::MerchantJWT {
+                merchant_id: payload.merchant_id,
+                user_id: Some(payload.user_id),
+            },
+        ))
     }
 }
 
+pub struct JWTAuthMerchantFromRoute {
+    pub merchant_id: String,
+}
+
+#[async_trait]
+impl<A> AuthenticateAndFetch<(), A> for JWTAuthMerchantFromRoute
+where
+    A: AppStateInfo + Sync,
+{
+    async fn authenticate_and_fetch(
+        &self,
+        request_headers: &HeaderMap,
+        state: &A,
+    ) -> RouterResult<((), AuthenticationType)> {
+        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
+
+        // Check if token has access to merchantID that has been requested through query param
+        if payload.merchant_id != self.merchant_id {
+            return Err(report!(errors::ApiErrorResponse::InvalidJwtToken));
+        }
+        Ok((
+            (),
+            AuthenticationType::MerchantJWT {
+                merchant_id: payload.merchant_id,
+                user_id: Some(payload.user_id),
+            },
+        ))
+    }
+}
+
+pub async fn parse_jwt_payload<A, T>(headers: &HeaderMap, state: &A) -> RouterResult<T>
+where
+    T: serde::de::DeserializeOwned,
+    A: AppStateInfo + Sync,
+{
+    let token = get_jwt_from_authorization_header(headers)?;
+    let payload = decode_jwt(token, state).await?;
+
+    Ok(payload)
+}
+
 #[derive(serde::Deserialize)]
 struct JwtAuthPayloadFetchMerchantAccount {
     merchant_id: String,
@@ -323,10 +467,10 @@ where
         &self,
         request_headers: &HeaderMap,
         state: &A,
-    ) -> RouterResult<AuthenticationData> {
-        let mut token = get_jwt(request_headers)?;
-        token = strip_jwt_token(token)?;
-        let payload = decode_jwt::<JwtAuthPayloadFetchMerchantAccount>(token, state).await?;
+    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
+        let payload =
+            parse_jwt_payload::<A, JwtAuthPayloadFetchMerchantAccount>(request_headers, state)
+                .await?;
         let key_store = state
             .store()
             .get_merchant_key_store_by_merchant_id(
@@ -343,10 +487,17 @@ where
             .await
             .change_context(errors::ApiErrorResponse::InvalidJwtToken)?;
 
-        Ok(AuthenticationData {
+        let auth = AuthenticationData {
             merchant_account: merchant,
             key_store,
-        })
+        };
+        Ok((
+            auth.clone(),
+            AuthenticationType::MerchantJWT {
+                merchant_id: auth.merchant_account.merchant_id.clone(),
+                user_id: None,
+            },
+        ))
     }
 }
 
@@ -523,14 +674,16 @@ pub fn get_header_value_by_key(key: String, headers: &HeaderMap) -> RouterResult
         .transpose()
 }
 
-pub fn get_jwt(headers: &HeaderMap) -> RouterResult<&str> {
+pub fn get_jwt_from_authorization_header(headers: &HeaderMap) -> RouterResult<&str> {
     headers
         .get(crate::headers::AUTHORIZATION)
         .get_required_value(crate::headers::AUTHORIZATION)?
         .to_str()
         .into_report()
         .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("Failed to convert JWT token to string")
+        .attach_printable("Failed to convert JWT token to string")?
+        .strip_prefix("Bearer ")
+        .ok_or(errors::ApiErrorResponse::InvalidJwtToken.into())
 }
 
 pub fn strip_jwt_token(token: &str) -> RouterResult<&str> {
diff --git a/crates/router/src/services/jwt.rs b/crates/router/src/services/jwt.rs
new file mode 100644
index 000000000000..b69a21583919
--- /dev/null
+++ b/crates/router/src/services/jwt.rs
@@ -0,0 +1,42 @@
+use common_utils::errors::CustomResult;
+use error_stack::{IntoReport, ResultExt};
+use jsonwebtoken::{encode, EncodingKey, Header};
+use masking::PeekInterface;
+
+use super::authentication;
+use crate::{configs::settings::Settings, core::errors::UserErrors};
+
+pub fn generate_exp(
+    exp_duration: std::time::Duration,
+) -> CustomResult<std::time::Duration, UserErrors> {
+    std::time::SystemTime::now()
+        .checked_add(exp_duration)
+        .ok_or(UserErrors::InternalServerError)?
+        .duration_since(std::time::UNIX_EPOCH)
+        .into_report()
+        .change_context(UserErrors::InternalServerError)
+}
+
+pub async fn generate_jwt<T>(
+    claims_data: &T,
+    settings: &Settings,
+) -> CustomResult<String, UserErrors>
+where
+    T: serde::ser::Serialize,
+{
+    let jwt_secret = authentication::get_jwt_secret(
+        &settings.secrets,
+        #[cfg(feature = "kms")]
+        external_services::kms::get_kms_client(&settings.kms).await,
+    )
+    .await
+    .change_context(UserErrors::InternalServerError)
+    .attach_printable("Failed to obtain JWT secret")?;
+    encode(
+        &Header::default(),
+        claims_data,
+        &EncodingKey::from_secret(jwt_secret.peek().as_bytes()),
+    )
+    .into_report()
+    .change_context(UserErrors::InternalServerError)
+}
diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs
index 2f1bce49e0fa..7e9725d1a3b7 100644
--- a/crates/router/src/types.rs
+++ b/crates/router/src/types.rs
@@ -547,11 +547,31 @@ pub trait Capturable {
     fn get_capture_amount(&self) -> Option<i64> {
         Some(0)
     }
+    fn get_surcharge_amount(&self) -> Option<i64> {
+        None
+    }
+    fn get_tax_on_surcharge_amount(&self) -> Option<i64> {
+        None
+    }
 }
 
 impl Capturable for PaymentsAuthorizeData {
     fn get_capture_amount(&self) -> Option<i64> {
-        Some(self.amount)
+        let final_amount = self
+            .surcharge_details
+            .as_ref()
+            .map(|surcharge_details| surcharge_details.final_amount);
+        final_amount.or(Some(self.amount))
+    }
+    fn get_surcharge_amount(&self) -> Option<i64> {
+        self.surcharge_details
+            .as_ref()
+            .map(|surcharge_details| surcharge_details.surcharge_amount)
+    }
+    fn get_tax_on_surcharge_amount(&self) -> Option<i64> {
+        self.surcharge_details
+            .as_ref()
+            .map(|surcharge_details| surcharge_details.tax_on_surcharge_amount)
     }
 }
 
@@ -834,10 +854,12 @@ pub struct DefendDisputeResponse {
     pub connector_status: Option<String>,
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, serde::Serialize)]
 pub struct UploadFileRequestData {
     pub file_key: String,
+    #[serde(skip)]
     pub file: Vec<u8>,
+    #[serde(serialize_with = "crate::utils::custom_serde::display_serialize")]
     pub file_type: mime::Mime,
     pub file_size: i32,
 }
@@ -921,6 +943,7 @@ pub struct ErrorResponse {
     pub message: String,
     pub reason: Option<String>,
     pub status_code: u16,
+    pub attempt_status: Option<storage_enums::AttemptStatus>,
 }
 
 impl ErrorResponse {
@@ -936,6 +959,7 @@ impl ErrorResponse {
             .error_message(),
             reason: None,
             status_code: http::StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
+            attempt_status: None,
         }
     }
 }
@@ -956,6 +980,11 @@ impl TryFrom<ConnectorAuthType> for AccessTokenRequestData {
                 app_id: api_key,
                 id: Some(key1),
             }),
+            ConnectorAuthType::MultiAuthKey { api_key, key1, .. } => Ok(Self {
+                app_id: api_key,
+                id: Some(key1),
+            }),
+
             _ => Err(errors::ApiErrorResponse::InvalidDataValue {
                 field_name: "connector_account_details",
             }),
@@ -973,6 +1002,7 @@ impl From<errors::ApiErrorResponse> for ErrorResponse {
                 errors::ApiErrorResponse::ExternalConnectorError { status_code, .. } => status_code,
                 _ => 500,
             },
+            attempt_status: None,
         }
     }
 }
@@ -1183,3 +1213,5 @@ impl<F1, F2>
         }
     }
 }
+
+pub type GsmResponse = storage::GatewayStatusMap;
diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs
index f3072d697c76..5aeae7d8913e 100644
--- a/crates/router/src/types/api.rs
+++ b/crates/router/src/types/api.rs
@@ -11,10 +11,12 @@ pub mod payment_methods;
 pub mod payments;
 pub mod payouts;
 pub mod refunds;
+pub mod routing;
 pub mod webhooks;
 
 use std::{fmt::Debug, str::FromStr};
 
+use api_models::payment_methods::{SurchargeDetailsResponse, SurchargeMetadata};
 use error_stack::{report, IntoReport, ResultExt};
 
 pub use self::{
@@ -38,6 +40,13 @@ pub trait ConnectorAccessToken:
 {
 }
 
+#[derive(Clone)]
+pub enum ConnectorCallType {
+    PreDetermined(ConnectorData),
+    Retryable(Vec<ConnectorData>),
+    SessionMultiple(Vec<SessionConnectorData>),
+}
+
 #[derive(Clone, Debug)]
 pub struct VerifyWebhookSource;
 
@@ -103,6 +112,7 @@ pub trait ConnectorCommon {
             code: consts::NO_ERROR_CODE.to_string(),
             message: consts::NO_ERROR_MESSAGE.to_string(),
             reason: None,
+            attempt_status: None,
         })
     }
 }
@@ -171,11 +181,15 @@ pub enum GetToken {
     Connector,
 }
 
+/// Routing algorithm will output merchant connector identifier instead of connector name
+/// In order to support backwards compatibility for older routing algorithms and merchant accounts
+/// the support for connector name is retained
 #[derive(Clone)]
 pub struct ConnectorData {
     pub connector: BoxedConnector,
     pub connector_name: types::Connector,
     pub get_token: GetToken,
+    pub merchant_connector_id: Option<String>,
 }
 
 #[cfg(feature = "payouts")]
@@ -201,6 +215,30 @@ pub struct SessionConnectorData {
     pub business_sub_label: Option<String>,
 }
 
+/// Session Surcharge type
+pub enum SessionSurchargeDetails {
+    /// Surcharge is calculated by hyperswitch
+    Calculated(SurchargeMetadata),
+    /// Surcharge is sent by merchant
+    PreDetermined(SurchargeDetailsResponse),
+}
+
+impl SessionSurchargeDetails {
+    pub fn fetch_surcharge_details(
+        &self,
+        payment_method: &enums::PaymentMethod,
+        payment_method_type: &enums::PaymentMethodType,
+        card_network: Option<&enums::CardNetwork>,
+    ) -> Option<SurchargeDetailsResponse> {
+        match self {
+            Self::Calculated(surcharge_metadata) => surcharge_metadata
+                .get_surcharge_details(payment_method, payment_method_type, card_network)
+                .cloned(),
+            Self::PreDetermined(surcharge_details) => Some(surcharge_details.clone()),
+        }
+    }
+}
+
 pub enum ConnectorChoice {
     SessionMultiple(Vec<SessionConnectorData>),
     StraightThrough(serde_json::Value),
@@ -214,12 +252,6 @@ pub enum PayoutConnectorChoice {
     Decide,
 }
 
-#[derive(Clone)]
-pub enum ConnectorCallType {
-    Multiple(Vec<SessionConnectorData>),
-    Single(ConnectorData),
-}
-
 #[cfg(feature = "payouts")]
 #[derive(Clone)]
 pub enum PayoutConnectorCallType {
@@ -227,12 +259,6 @@ pub enum PayoutConnectorCallType {
     Single(PayoutConnectorData),
 }
 
-impl ConnectorCallType {
-    pub fn is_single(&self) -> bool {
-        matches!(self, Self::Single(_))
-    }
-}
-
 #[cfg(feature = "payouts")]
 impl PayoutConnectorData {
     pub fn get_connector_by_name(
@@ -276,6 +302,7 @@ impl ConnectorData {
         connectors: &Connectors,
         name: &str,
         connector_type: GetToken,
+        connector_id: Option<String>,
     ) -> CustomResult<Self, errors::ApiErrorResponse> {
         let connector = Self::convert_connector(connectors, name)?;
         let connector_name = api_enums::Connector::from_str(name)
@@ -287,6 +314,7 @@ impl ConnectorData {
             connector,
             connector_name,
             get_token: connector_type,
+            merchant_connector_id: connector_id,
         })
     }
 
@@ -301,6 +329,7 @@ impl ConnectorData {
                 enums::Connector::Airwallex => Ok(Box::new(&connector::Airwallex)),
                 enums::Connector::Authorizedotnet => Ok(Box::new(&connector::Authorizedotnet)),
                 enums::Connector::Bambora => Ok(Box::new(&connector::Bambora)),
+                // enums::Connector::Bankofamerica => Ok(Box::new(&connector::Bankofamerica)), Added as template code for future usage
                 enums::Connector::Bitpay => Ok(Box::new(&connector::Bitpay)),
                 enums::Connector::Bluesnap => Ok(Box::new(&connector::Bluesnap)),
                 enums::Connector::Boku => Ok(Box::new(&connector::Boku)),
@@ -356,7 +385,7 @@ impl ConnectorData {
                 enums::Connector::Paypal => Ok(Box::new(&connector::Paypal)),
                 enums::Connector::Trustpay => Ok(Box::new(&connector::Trustpay)),
                 enums::Connector::Tsys => Ok(Box::new(&connector::Tsys)),
-                // enums::Connector::Volt => Ok(Box::new(&connector::Volt)), it is added as template code for future usage
+                enums::Connector::Volt => Ok(Box::new(&connector::Volt)),
                 enums::Connector::Zen => Ok(Box::new(&connector::Zen)),
                 enums::Connector::Signifyd | enums::Connector::Plaid => {
                     Err(report!(errors::ConnectorError::InvalidConnectorName)
diff --git a/crates/router/src/types/api/admin.rs b/crates/router/src/types/api/admin.rs
index 258a3d566dde..6bbe9149f4d7 100644
--- a/crates/router/src/types/api/admin.rs
+++ b/crates/router/src/types/api/admin.rs
@@ -4,8 +4,8 @@ pub use api_models::admin::{
     MerchantAccountResponse, MerchantAccountUpdate, MerchantConnectorCreate,
     MerchantConnectorDeleteResponse, MerchantConnectorDetails, MerchantConnectorDetailsWrap,
     MerchantConnectorId, MerchantConnectorResponse, MerchantDetails, MerchantId,
-    PaymentMethodsEnabled, PayoutRoutingAlgorithm, PayoutStraightThroughAlgorithm,
-    RoutingAlgorithm, StraightThroughAlgorithm, ToggleKVRequest, ToggleKVResponse, WebhookDetails,
+    PaymentMethodsEnabled, PayoutRoutingAlgorithm, PayoutStraightThroughAlgorithm, ToggleKVRequest,
+    ToggleKVResponse, WebhookDetails,
 };
 use common_utils::ext_traits::ValueExt;
 use error_stack::ResultExt;
diff --git a/crates/router/src/types/api/configs.rs b/crates/router/src/types/api/configs.rs
index 9e39d5569b05..dbe8b0603af6 100644
--- a/crates/router/src/types/api/configs.rs
+++ b/crates/router/src/types/api/configs.rs
@@ -4,7 +4,7 @@ pub struct Config {
     pub value: String,
 }
 
-#[derive(Clone, serde::Deserialize, Debug)]
+#[derive(Clone, serde::Deserialize, Debug, serde::Serialize)]
 pub struct ConfigUpdate {
     #[serde(skip_deserializing)]
     pub key: String,
diff --git a/crates/router/src/types/api/customers.rs b/crates/router/src/types/api/customers.rs
index 2050b4149ef8..32430c0918a2 100644
--- a/crates/router/src/types/api/customers.rs
+++ b/crates/router/src/types/api/customers.rs
@@ -10,6 +10,12 @@ newtype!(
     derives = (Debug, Clone, Serialize)
 );
 
+impl common_utils::events::ApiEventMetric for CustomerResponse {
+    fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
+        self.0.get_api_event_type()
+    }
+}
+
 pub(crate) trait CustomerRequestExt: Sized {
     fn validate(self) -> RouterResult<Self>;
 }
diff --git a/crates/router/src/types/api/disputes.rs b/crates/router/src/types/api/disputes.rs
index 4339554fdc4a..85fdb307ed68 100644
--- a/crates/router/src/types/api/disputes.rs
+++ b/crates/router/src/types/api/disputes.rs
@@ -36,13 +36,13 @@ pub struct DisputeEvidence {
     pub uncategorized_file: Option<String>,
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Serialize)]
 pub struct AttachEvidenceRequest {
     pub create_file_request: types::api::CreateFileRequest,
     pub evidence_type: EvidenceType,
 }
 
-#[derive(Debug, serde::Deserialize, strum::Display, strum::EnumString, Clone)]
+#[derive(Debug, serde::Deserialize, strum::Display, strum::EnumString, Clone, serde::Serialize)]
 #[serde(rename_all = "snake_case")]
 #[strum(serialize_all = "snake_case")]
 pub enum EvidenceType {
diff --git a/crates/router/src/types/api/files.rs b/crates/router/src/types/api/files.rs
index 1e78708c8180..873516ee71bc 100644
--- a/crates/router/src/types/api/files.rs
+++ b/crates/router/src/types/api/files.rs
@@ -47,17 +47,18 @@ impl ForeignTryFrom<&types::Connector> for FileUploadProvider {
     }
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, serde::Serialize)]
 pub struct CreateFileRequest {
     pub file: Vec<u8>,
     pub file_name: Option<String>,
     pub file_size: i32,
+    #[serde(serialize_with = "crate::utils::custom_serde::display_serialize")]
     pub file_type: mime::Mime,
     pub purpose: FilePurpose,
     pub dispute_id: Option<String>,
 }
 
-#[derive(Debug, serde::Deserialize, strum::Display, Clone)]
+#[derive(Debug, serde::Deserialize, strum::Display, Clone, serde::Serialize)]
 #[serde(rename_all = "snake_case")]
 #[strum(serialize_all = "snake_case")]
 pub enum FilePurpose {
diff --git a/crates/router/src/types/api/payment_methods.rs b/crates/router/src/types/api/payment_methods.rs
index 39ef57dfa9fd..5acb66b5068e 100644
--- a/crates/router/src/types/api/payment_methods.rs
+++ b/crates/router/src/types/api/payment_methods.rs
@@ -1,9 +1,9 @@
 use api_models::enums as api_enums;
 pub use api_models::payment_methods::{
     CardDetail, CardDetailFromLocker, CardDetailsPaymentMethod, CustomerPaymentMethod,
-    CustomerPaymentMethodsListResponse, GetTokenizePayloadRequest, GetTokenizePayloadResponse,
-    PaymentMethodCreate, PaymentMethodDeleteResponse, PaymentMethodId, PaymentMethodList,
-    PaymentMethodListRequest, PaymentMethodListResponse, PaymentMethodResponse,
+    CustomerPaymentMethodsListResponse, DeleteTokenizeByTokenRequest, GetTokenizePayloadRequest,
+    GetTokenizePayloadResponse, PaymentMethodCreate, PaymentMethodDeleteResponse, PaymentMethodId,
+    PaymentMethodList, PaymentMethodListRequest, PaymentMethodListResponse, PaymentMethodResponse,
     PaymentMethodUpdate, PaymentMethodsData, TokenizePayloadEncrypted, TokenizePayloadRequest,
     TokenizedCardValue1, TokenizedCardValue2, TokenizedWalletValue1, TokenizedWalletValue2,
 };
diff --git a/crates/router/src/types/api/routing.rs b/crates/router/src/types/api/routing.rs
new file mode 100644
index 000000000000..faafac76e3dc
--- /dev/null
+++ b/crates/router/src/types/api/routing.rs
@@ -0,0 +1,41 @@
+#[cfg(feature = "backwards_compatibility")]
+pub use api_models::routing::RoutableChoiceKind;
+pub use api_models::{
+    enums as api_enums,
+    routing::{
+        ConnectorVolumeSplit, DetailedConnectorChoice, RoutableConnectorChoice, RoutingAlgorithm,
+        RoutingAlgorithmKind, RoutingAlgorithmRef, RoutingConfigRequest, RoutingDictionary,
+        RoutingDictionaryRecord, StraightThroughAlgorithm,
+    },
+};
+
+use super::types::api as api_oss;
+
+pub struct SessionRoutingChoice {
+    pub connector: api_oss::ConnectorData,
+    #[cfg(not(feature = "connector_choice_mca_id"))]
+    pub sub_label: Option<String>,
+    pub payment_method_type: api_enums::PaymentMethodType,
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct ConnectorVolumeSplitV0 {
+    pub connector: RoutableConnectorChoice,
+    pub split: u8,
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+#[serde(tag = "type", content = "data", rename_all = "snake_case")]
+pub enum RoutingAlgorithmV0 {
+    Single(Box<RoutableConnectorChoice>),
+    Priority(Vec<RoutableConnectorChoice>),
+    VolumeSplit(Vec<ConnectorVolumeSplitV0>),
+    Custom { timestamp: i64 },
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct FrmRoutingAlgorithm {
+    pub data: String,
+    #[serde(rename = "type")]
+    pub algorithm_type: String,
+}
diff --git a/crates/router/src/types/api/webhooks.rs b/crates/router/src/types/api/webhooks.rs
index 70a40f466c83..4bde2608c93a 100644
--- a/crates/router/src/types/api/webhooks.rs
+++ b/crates/router/src/types/api/webhooks.rs
@@ -156,6 +156,7 @@ pub trait IncomingWebhook: ConnectorCommon + Sync {
             &state.conf.connectors,
             connector_name,
             types::api::GetToken::Connector,
+            None,
         )
         .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
         .attach_printable("invalid connector name received in payment attempt")?;
diff --git a/crates/router/src/types/domain.rs b/crates/router/src/types/domain.rs
index 44123850d468..c93f96eaf09e 100644
--- a/crates/router/src/types/domain.rs
+++ b/crates/router/src/types/domain.rs
@@ -5,9 +5,13 @@ mod merchant_account;
 mod merchant_connector_account;
 mod merchant_key_store;
 pub mod types;
+#[cfg(feature = "olap")]
+pub mod user;
 
 pub use address::*;
 pub use customer::*;
 pub use merchant_account::*;
 pub use merchant_connector_account::*;
 pub use merchant_key_store::*;
+#[cfg(feature = "olap")]
+pub use user::*;
diff --git a/crates/router/src/types/domain/address.rs b/crates/router/src/types/domain/address.rs
index 008cead1ebeb..ddf9c2152e94 100644
--- a/crates/router/src/types/domain/address.rs
+++ b/crates/router/src/types/domain/address.rs
@@ -35,7 +35,7 @@ pub struct Address {
     #[serde(skip_serializing)]
     #[serde(with = "custom_serde::iso8601")]
     pub modified_at: PrimitiveDateTime,
-    pub customer_id: String,
+    pub customer_id: Option<String>,
     pub merchant_id: String,
     pub payment_id: Option<String>,
     pub updated_by: String,
diff --git a/crates/router/src/types/domain/customer.rs b/crates/router/src/types/domain/customer.rs
index 3810523b413f..fe575851dc49 100644
--- a/crates/router/src/types/domain/customer.rs
+++ b/crates/router/src/types/domain/customer.rs
@@ -99,7 +99,7 @@ impl super::behaviour::Conversion for Customer {
     }
 }
 
-#[derive(Debug)]
+#[derive(Clone, Debug)]
 pub enum CustomerUpdate {
     Update {
         name: crypto::OptionalEncryptableName,
diff --git a/crates/router/src/types/domain/user.rs b/crates/router/src/types/domain/user.rs
new file mode 100644
index 000000000000..c053b0f15448
--- /dev/null
+++ b/crates/router/src/types/domain/user.rs
@@ -0,0 +1,483 @@
+use std::{collections::HashSet, ops, str::FromStr};
+
+use api_models::{admin as admin_api, organization as api_org, user as user_api};
+use common_utils::pii;
+use diesel_models::{
+    enums::UserStatus,
+    organization as diesel_org,
+    organization::Organization,
+    user as storage_user,
+    user_role::{UserRole, UserRoleNew},
+};
+use error_stack::{IntoReport, ResultExt};
+use masking::{ExposeInterface, PeekInterface, Secret};
+use once_cell::sync::Lazy;
+use unicode_segmentation::UnicodeSegmentation;
+
+use crate::{
+    consts::user as consts,
+    core::{
+        admin,
+        errors::{UserErrors, UserResult},
+    },
+    db::StorageInterface,
+    routes::AppState,
+    services::authentication::AuthToken,
+    types::transformers::ForeignFrom,
+    utils::user::password,
+};
+
+#[derive(Clone)]
+pub struct UserName(Secret<String>);
+
+impl UserName {
+    pub fn new(name: Secret<String>) -> UserResult<Self> {
+        let name = name.expose();
+        let is_empty_or_whitespace = name.trim().is_empty();
+        let is_too_long = name.graphemes(true).count() > consts::MAX_NAME_LENGTH;
+
+        let forbidden_characters = ['/', '(', ')', '"', '<', '>', '\\', '{', '}'];
+        let contains_forbidden_characters = name.chars().any(|g| forbidden_characters.contains(&g));
+
+        if is_empty_or_whitespace || is_too_long || contains_forbidden_characters {
+            Err(UserErrors::NameParsingError.into())
+        } else {
+            Ok(Self(name.into()))
+        }
+    }
+
+    pub fn get_secret(self) -> Secret<String> {
+        self.0
+    }
+}
+
+impl TryFrom<pii::Email> for UserName {
+    type Error = error_stack::Report<UserErrors>;
+
+    fn try_from(value: pii::Email) -> UserResult<Self> {
+        Self::new(Secret::new(
+            value
+                .peek()
+                .split_once('@')
+                .ok_or(UserErrors::InvalidEmailError)?
+                .0
+                .to_string(),
+        ))
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct UserEmail(pii::Email);
+
+static BLOCKED_EMAIL: Lazy<HashSet<String>> = Lazy::new(|| {
+    let blocked_emails_content = include_str!("../../utils/user/blocker_emails.txt");
+    let blocked_emails: HashSet<String> = blocked_emails_content
+        .lines()
+        .map(|s| s.trim().to_owned())
+        .collect();
+    blocked_emails
+});
+
+impl UserEmail {
+    pub fn new(email: Secret<String, pii::EmailStrategy>) -> UserResult<Self> {
+        let email_string = email.expose();
+        let email =
+            pii::Email::from_str(&email_string).change_context(UserErrors::EmailParsingError)?;
+
+        if validator::validate_email(&email_string) {
+            let (_username, domain) = match email_string.as_str().split_once('@') {
+                Some((u, d)) => (u, d),
+                None => return Err(UserErrors::EmailParsingError.into()),
+            };
+
+            if BLOCKED_EMAIL.contains(domain) {
+                return Err(UserErrors::InvalidEmailError.into());
+            }
+            Ok(Self(email))
+        } else {
+            Err(UserErrors::EmailParsingError.into())
+        }
+    }
+
+    pub fn from_pii_email(email: pii::Email) -> UserResult<Self> {
+        let email_string = email.peek();
+        if validator::validate_email(email_string) {
+            let (_username, domain) = match email_string.split_once('@') {
+                Some((u, d)) => (u, d),
+                None => return Err(UserErrors::EmailParsingError.into()),
+            };
+            if BLOCKED_EMAIL.contains(domain) {
+                return Err(UserErrors::InvalidEmailError.into());
+            }
+            Ok(Self(email))
+        } else {
+            Err(UserErrors::EmailParsingError.into())
+        }
+    }
+
+    pub fn into_inner(self) -> pii::Email {
+        self.0
+    }
+
+    pub fn get_secret(self) -> Secret<String, pii::EmailStrategy> {
+        (*self.0).clone()
+    }
+}
+
+impl TryFrom<pii::Email> for UserEmail {
+    type Error = error_stack::Report<UserErrors>;
+
+    fn try_from(value: pii::Email) -> Result<Self, Self::Error> {
+        Self::from_pii_email(value)
+    }
+}
+
+impl ops::Deref for UserEmail {
+    type Target = Secret<String, pii::EmailStrategy>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+#[derive(Clone)]
+pub struct UserPassword(Secret<String>);
+
+impl UserPassword {
+    pub fn new(password: Secret<String>) -> UserResult<Self> {
+        let password = password.expose();
+        if password.is_empty() {
+            Err(UserErrors::PasswordParsingError.into())
+        } else {
+            Ok(Self(password.into()))
+        }
+    }
+
+    pub fn get_secret(&self) -> Secret<String> {
+        self.0.clone()
+    }
+}
+
+#[derive(Clone)]
+pub struct UserCompanyName(String);
+
+impl UserCompanyName {
+    pub fn new(company_name: String) -> UserResult<Self> {
+        let company_name = company_name.trim();
+        let is_empty_or_whitespace = company_name.is_empty();
+        let is_too_long = company_name.graphemes(true).count() > consts::MAX_COMPANY_NAME_LENGTH;
+
+        let is_all_valid_characters = company_name
+            .chars()
+            .all(|x| x.is_alphanumeric() || x.is_ascii_whitespace() || x == '_');
+        if is_empty_or_whitespace || is_too_long || !is_all_valid_characters {
+            Err(UserErrors::CompanyNameParsingError.into())
+        } else {
+            Ok(Self(company_name.to_string()))
+        }
+    }
+
+    pub fn get_secret(self) -> String {
+        self.0
+    }
+}
+
+#[derive(Clone)]
+pub struct NewUserOrganization(diesel_org::OrganizationNew);
+
+impl NewUserOrganization {
+    pub async fn insert_org_in_db(self, state: AppState) -> UserResult<Organization> {
+        state
+            .store
+            .insert_organization(self.0)
+            .await
+            .map_err(|e| {
+                if e.current_context().is_db_unique_violation() {
+                    e.change_context(UserErrors::DuplicateOrganizationId)
+                } else {
+                    e.change_context(UserErrors::InternalServerError)
+                }
+            })
+            .attach_printable("Error while inserting organization")
+    }
+
+    pub fn get_organization_id(&self) -> String {
+        self.0.org_id.clone()
+    }
+}
+
+impl From<user_api::ConnectAccountRequest> for NewUserOrganization {
+    fn from(_value: user_api::ConnectAccountRequest) -> Self {
+        let new_organization = api_org::OrganizationNew::new(None);
+        let db_organization = ForeignFrom::foreign_from(new_organization);
+        Self(db_organization)
+    }
+}
+
+#[derive(Clone)]
+pub struct NewUserMerchant {
+    merchant_id: String,
+    company_name: Option<UserCompanyName>,
+    new_organization: NewUserOrganization,
+}
+
+impl NewUserMerchant {
+    pub fn get_company_name(&self) -> Option<String> {
+        self.company_name.clone().map(UserCompanyName::get_secret)
+    }
+
+    pub fn get_merchant_id(&self) -> String {
+        self.merchant_id.clone()
+    }
+
+    pub fn get_new_organization(&self) -> NewUserOrganization {
+        self.new_organization.clone()
+    }
+
+    pub async fn check_if_already_exists_in_db(&self, state: AppState) -> UserResult<()> {
+        if state
+            .store
+            .get_merchant_key_store_by_merchant_id(
+                self.get_merchant_id().as_str(),
+                &state.store.get_master_key().to_vec().into(),
+            )
+            .await
+            .is_ok()
+        {
+            return Err(UserErrors::MerchantAccountCreationError(format!(
+                "Merchant with {} already exists",
+                self.get_merchant_id()
+            )))
+            .into_report();
+        }
+        Ok(())
+    }
+
+    pub async fn create_new_merchant_and_insert_in_db(&self, state: AppState) -> UserResult<()> {
+        self.check_if_already_exists_in_db(state.clone()).await?;
+        Box::pin(admin::create_merchant_account(
+            state.clone(),
+            admin_api::MerchantAccountCreate {
+                merchant_id: self.get_merchant_id(),
+                metadata: None,
+                locker_id: None,
+                return_url: None,
+                merchant_name: self.get_company_name().map(Secret::new),
+                webhook_details: None,
+                publishable_key: None,
+                organization_id: Some(self.new_organization.get_organization_id()),
+                merchant_details: None,
+                routing_algorithm: None,
+                parent_merchant_id: None,
+                payment_link_config: None,
+                sub_merchants_enabled: None,
+                frm_routing_algorithm: None,
+                intent_fulfillment_time: None,
+                payout_routing_algorithm: None,
+                primary_business_details: None,
+                payment_response_hash_key: None,
+                enable_payment_response_hash: None,
+                redirect_to_merchant_with_http_post: None,
+            },
+        ))
+        .await
+        .change_context(UserErrors::InternalServerError)
+        .attach_printable("Error while creating a merchant")?;
+        Ok(())
+    }
+}
+
+impl TryFrom<user_api::ConnectAccountRequest> for NewUserMerchant {
+    type Error = error_stack::Report<UserErrors>;
+
+    fn try_from(value: user_api::ConnectAccountRequest) -> UserResult<Self> {
+        let merchant_id = format!("merchant_{}", common_utils::date_time::now_unix_timestamp());
+        let new_organization = NewUserOrganization::from(value);
+
+        Ok(Self {
+            company_name: None,
+            merchant_id,
+            new_organization,
+        })
+    }
+}
+
+#[derive(Clone)]
+pub struct NewUser {
+    user_id: String,
+    name: UserName,
+    email: UserEmail,
+    password: UserPassword,
+    new_merchant: NewUserMerchant,
+}
+
+impl NewUser {
+    pub fn get_user_id(&self) -> String {
+        self.user_id.clone()
+    }
+
+    pub fn get_email(&self) -> UserEmail {
+        self.email.clone()
+    }
+
+    pub fn get_name(&self) -> Secret<String> {
+        self.name.clone().get_secret()
+    }
+
+    pub fn get_new_merchant(&self) -> NewUserMerchant {
+        self.new_merchant.clone()
+    }
+
+    pub async fn insert_user_in_db(
+        &self,
+        db: &dyn StorageInterface,
+    ) -> UserResult<UserFromStorage> {
+        match db.insert_user(self.clone().try_into()?).await {
+            Ok(user) => Ok(user.into()),
+            Err(e) => {
+                if e.current_context().is_db_unique_violation() {
+                    return Err(e.change_context(UserErrors::UserExists));
+                } else {
+                    return Err(e.change_context(UserErrors::InternalServerError));
+                }
+            }
+        }
+        .attach_printable("Error while inserting user")
+    }
+
+    pub async fn insert_user_and_merchant_in_db(
+        &self,
+        state: AppState,
+    ) -> UserResult<UserFromStorage> {
+        let db = state.store.as_ref();
+        let merchant_id = self.get_new_merchant().get_merchant_id();
+        self.new_merchant
+            .create_new_merchant_and_insert_in_db(state.clone())
+            .await?;
+        let created_user = self.insert_user_in_db(db).await;
+        if created_user.is_err() {
+            let _ = admin::merchant_account_delete(state, merchant_id).await;
+        };
+        created_user
+    }
+
+    pub async fn insert_user_role_in_db(
+        self,
+        state: AppState,
+        role_id: String,
+        user_status: UserStatus,
+    ) -> UserResult<UserRole> {
+        let now = common_utils::date_time::now();
+        let user_id = self.get_user_id();
+
+        state
+            .store
+            .insert_user_role(UserRoleNew {
+                merchant_id: self.get_new_merchant().get_merchant_id(),
+                status: user_status,
+                created_by: user_id.clone(),
+                last_modified_by: user_id.clone(),
+                user_id,
+                role_id,
+                created_at: now,
+                last_modified_at: now,
+                org_id: self
+                    .get_new_merchant()
+                    .get_new_organization()
+                    .get_organization_id(),
+            })
+            .await
+            .change_context(UserErrors::InternalServerError)
+    }
+}
+
+impl TryFrom<NewUser> for storage_user::UserNew {
+    type Error = error_stack::Report<UserErrors>;
+
+    fn try_from(value: NewUser) -> UserResult<Self> {
+        let hashed_password = password::generate_password_hash(value.password.get_secret())?;
+        Ok(Self {
+            user_id: value.get_user_id(),
+            name: value.get_name(),
+            email: value.get_email().into_inner(),
+            password: hashed_password,
+            ..Default::default()
+        })
+    }
+}
+
+impl TryFrom<user_api::ConnectAccountRequest> for NewUser {
+    type Error = error_stack::Report<UserErrors>;
+
+    fn try_from(value: user_api::ConnectAccountRequest) -> UserResult<Self> {
+        let user_id = uuid::Uuid::new_v4().to_string();
+        let email = value.email.clone().try_into()?;
+        let name = UserName::try_from(value.email.clone())?;
+        let password = UserPassword::new(value.password.clone())?;
+        let new_merchant = NewUserMerchant::try_from(value)?;
+
+        Ok(Self {
+            user_id,
+            name,
+            email,
+            password,
+            new_merchant,
+        })
+    }
+}
+
+pub struct UserFromStorage(pub storage_user::User);
+
+impl From<storage_user::User> for UserFromStorage {
+    fn from(value: storage_user::User) -> Self {
+        Self(value)
+    }
+}
+
+impl UserFromStorage {
+    pub fn get_user_id(&self) -> &str {
+        self.0.user_id.as_str()
+    }
+
+    pub fn compare_password(&self, candidate: Secret<String>) -> UserResult<()> {
+        match password::is_correct_password(candidate, self.0.password.clone()) {
+            Ok(true) => Ok(()),
+            Ok(false) => Err(UserErrors::InvalidCredentials.into()),
+            Err(e) => Err(e),
+        }
+    }
+
+    pub fn get_name(&self) -> Secret<String> {
+        self.0.name.clone()
+    }
+
+    pub fn get_email(&self) -> pii::Email {
+        self.0.email.clone()
+    }
+
+    pub async fn get_jwt_auth_token(&self, state: AppState, org_id: String) -> UserResult<String> {
+        let role_id = self.get_role_from_db(state.clone()).await?.role_id;
+        let merchant_id = state
+            .store
+            .find_user_role_by_user_id(self.get_user_id())
+            .await
+            .change_context(UserErrors::InternalServerError)?
+            .merchant_id;
+        AuthToken::new_token(
+            self.0.user_id.clone(),
+            merchant_id,
+            role_id,
+            &state.conf,
+            org_id,
+        )
+        .await
+    }
+
+    pub async fn get_role_from_db(&self, state: AppState) -> UserResult<UserRole> {
+        state
+            .store
+            .find_user_role_by_user_id(self.get_user_id())
+            .await
+            .change_context(UserErrors::InternalServerError)
+    }
+}
diff --git a/crates/router/src/types/storage.rs b/crates/router/src/types/storage.rs
index 92ead76e9137..e3e19323357b 100644
--- a/crates/router/src/types/storage.rs
+++ b/crates/router/src/types/storage.rs
@@ -4,13 +4,13 @@ pub mod business_profile;
 pub mod capture;
 pub mod cards_info;
 pub mod configs;
-pub mod connector_response;
 pub mod customers;
 pub mod dispute;
 pub mod enums;
 pub mod ephemeral_key;
 pub mod events;
 pub mod file;
+pub mod gsm;
 #[cfg(feature = "kv_store")]
 pub mod kv;
 pub mod locker_mock_up;
@@ -21,6 +21,9 @@ pub mod merchant_key_store;
 pub mod payment_attempt;
 pub mod payment_link;
 pub mod payment_method;
+pub mod routing_algorithm;
+use std::collections::HashMap;
+
 pub use diesel_models::{ProcessTracker, ProcessTrackerNew, ProcessTrackerUpdate};
 pub use scheduler::db::process_tracker;
 pub mod reverse_lookup;
@@ -29,6 +32,8 @@ pub mod payout_attempt;
 pub mod payouts;
 mod query;
 pub mod refund;
+pub mod user;
+pub mod user_role;
 
 pub use data_models::payments::{
     payment_attempt::{PaymentAttempt, PaymentAttemptNew, PaymentAttemptUpdate},
@@ -37,15 +42,67 @@ pub use data_models::payments::{
 };
 
 pub use self::{
-    address::*, api_keys::*, capture::*, cards_info::*, configs::*, connector_response::*,
-    customers::*, dispute::*, ephemeral_key::*, events::*, file::*, locker_mock_up::*, mandate::*,
+    address::*, api_keys::*, capture::*, cards_info::*, configs::*, customers::*, dispute::*,
+    ephemeral_key::*, events::*, file::*, gsm::*, locker_mock_up::*, mandate::*,
     merchant_account::*, merchant_connector_account::*, merchant_key_store::*, payment_link::*,
     payment_method::*, payout_attempt::*, payouts::*, process_tracker::*, refund::*,
-    reverse_lookup::*,
+    reverse_lookup::*, routing_algorithm::*, user::*, user_role::*,
 };
+use crate::types::api::routing;
 
 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 pub struct RoutingData {
     pub routed_through: Option<String>,
-    pub algorithm: Option<api_models::admin::StraightThroughAlgorithm>,
+    #[cfg(feature = "connector_choice_mca_id")]
+    pub merchant_connector_id: Option<String>,
+    #[cfg(not(feature = "connector_choice_mca_id"))]
+    pub business_sub_label: Option<String>,
+    pub routing_info: PaymentRoutingInfo,
+    pub algorithm: Option<api_models::routing::StraightThroughAlgorithm>,
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+#[serde(from = "PaymentRoutingInfoSerde", into = "PaymentRoutingInfoSerde")]
+pub struct PaymentRoutingInfo {
+    pub algorithm: Option<routing::StraightThroughAlgorithm>,
+    pub pre_routing_results:
+        Option<HashMap<api_models::enums::PaymentMethodType, routing::RoutableConnectorChoice>>,
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct PaymentRoutingInfoInner {
+    pub algorithm: Option<routing::StraightThroughAlgorithm>,
+    pub pre_routing_results:
+        Option<HashMap<api_models::enums::PaymentMethodType, routing::RoutableConnectorChoice>>,
+}
+
+#[derive(Debug, serde::Serialize, serde::Deserialize)]
+#[serde(untagged)]
+pub enum PaymentRoutingInfoSerde {
+    OnlyAlgorithm(Box<routing::StraightThroughAlgorithm>),
+    WithDetails(Box<PaymentRoutingInfoInner>),
+}
+
+impl From<PaymentRoutingInfoSerde> for PaymentRoutingInfo {
+    fn from(value: PaymentRoutingInfoSerde) -> Self {
+        match value {
+            PaymentRoutingInfoSerde::OnlyAlgorithm(algo) => Self {
+                algorithm: Some(*algo),
+                pre_routing_results: None,
+            },
+            PaymentRoutingInfoSerde::WithDetails(details) => Self {
+                algorithm: details.algorithm,
+                pre_routing_results: details.pre_routing_results,
+            },
+        }
+    }
+}
+
+impl From<PaymentRoutingInfo> for PaymentRoutingInfoSerde {
+    fn from(value: PaymentRoutingInfo) -> Self {
+        Self::WithDetails(Box::new(PaymentRoutingInfoInner {
+            algorithm: value.algorithm,
+            pre_routing_results: value.pre_routing_results,
+        }))
+    }
 }
diff --git a/crates/router/src/types/storage/connector_response.rs b/crates/router/src/types/storage/connector_response.rs
deleted file mode 100644
index c93c231e3d1c..000000000000
--- a/crates/router/src/types/storage/connector_response.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-pub use diesel_models::{
-    connector_response::{
-        ConnectorResponse, ConnectorResponseNew, ConnectorResponseUpdate,
-        ConnectorResponseUpdateInternal,
-    },
-    enums::MerchantStorageScheme,
-};
-
-pub trait ConnectorResponseExt {
-    fn make_new_connector_response(
-        payment_id: String,
-        merchant_id: String,
-        attempt_id: String,
-        connector: Option<String>,
-        storage_scheme: String,
-    ) -> ConnectorResponseNew;
-}
-
-impl ConnectorResponseExt for ConnectorResponse {
-    fn make_new_connector_response(
-        payment_id: String,
-        merchant_id: String,
-        attempt_id: String,
-        connector: Option<String>,
-        storage_scheme: String,
-    ) -> ConnectorResponseNew {
-        let now = common_utils::date_time::now();
-        ConnectorResponseNew {
-            payment_id,
-            merchant_id,
-            attempt_id,
-            created_at: now,
-            modified_at: now,
-            connector_name: connector,
-            connector_transaction_id: None,
-            authentication_data: None,
-            encoded_data: None,
-            updated_by: storage_scheme,
-        }
-    }
-}
diff --git a/crates/router/src/types/storage/gsm.rs b/crates/router/src/types/storage/gsm.rs
new file mode 100644
index 000000000000..bcea00e90910
--- /dev/null
+++ b/crates/router/src/types/storage/gsm.rs
@@ -0,0 +1,4 @@
+pub use diesel_models::gsm::{
+    GatewayStatusMap, GatewayStatusMapperUpdateInternal, GatewayStatusMappingNew,
+    GatewayStatusMappingUpdate,
+};
diff --git a/crates/router/src/types/storage/kv.rs b/crates/router/src/types/storage/kv.rs
index 2afc73e6637d..6bb6c38e7b26 100644
--- a/crates/router/src/types/storage/kv.rs
+++ b/crates/router/src/types/storage/kv.rs
@@ -1,4 +1,4 @@
 pub use diesel_models::kv::{
-    AddressUpdateMems, ConnectorResponseUpdateMems, DBOperation, Insertable,
-    PaymentAttemptUpdateMems, PaymentIntentUpdateMems, RefundUpdateMems, TypedSql, Updateable,
+    AddressUpdateMems, DBOperation, Insertable, PaymentAttemptUpdateMems, PaymentIntentUpdateMems,
+    RefundUpdateMems, TypedSql, Updateable,
 };
diff --git a/crates/router/src/types/storage/refund.rs b/crates/router/src/types/storage/refund.rs
index bdfa8dc5b5ff..4d5667700122 100644
--- a/crates/router/src/types/storage/refund.rs
+++ b/crates/router/src/types/storage/refund.rs
@@ -27,7 +27,7 @@ pub trait RefundDbExt: Sized {
     async fn filter_by_meta_constraints(
         conn: &PgPooledConn,
         merchant_id: &str,
-        refund_list_details: &api_models::refunds::TimeRange,
+        refund_list_details: &api_models::payments::TimeRange,
     ) -> CustomResult<api_models::refunds::RefundListMetaData, errors::DatabaseError>;
 
     async fn get_refunds_count(
@@ -114,7 +114,7 @@ impl RefundDbExt for Refund {
     async fn filter_by_meta_constraints(
         conn: &PgPooledConn,
         merchant_id: &str,
-        refund_list_details: &api_models::refunds::TimeRange,
+        refund_list_details: &api_models::payments::TimeRange,
     ) -> CustomResult<api_models::refunds::RefundListMetaData, errors::DatabaseError> {
         let start_time = refund_list_details.start_time;
 
diff --git a/crates/router/src/types/storage/routing_algorithm.rs b/crates/router/src/types/storage/routing_algorithm.rs
new file mode 100644
index 000000000000..8022ab075ec4
--- /dev/null
+++ b/crates/router/src/types/storage/routing_algorithm.rs
@@ -0,0 +1,3 @@
+pub use diesel_models::routing_algorithm::{
+    RoutingAlgorithm, RoutingAlgorithmMetadata, RoutingProfileMetadata,
+};
diff --git a/crates/router/src/types/storage/user.rs b/crates/router/src/types/storage/user.rs
new file mode 100644
index 000000000000..17dc9d365243
--- /dev/null
+++ b/crates/router/src/types/storage/user.rs
@@ -0,0 +1 @@
+pub use diesel_models::user::*;
diff --git a/crates/router/src/types/storage/user_role.rs b/crates/router/src/types/storage/user_role.rs
new file mode 100644
index 000000000000..780b9b2971db
--- /dev/null
+++ b/crates/router/src/types/storage/user_role.rs
@@ -0,0 +1 @@
+pub use diesel_models::user_role::*;
diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs
index 84b4ffecab9d..71e2ff4f7a60 100644
--- a/crates/router/src/types/transformers.rs
+++ b/crates/router/src/types/transformers.rs
@@ -1,6 +1,6 @@
 // use actix_web::HttpMessage;
 use actix_web::http::header::HeaderMap;
-use api_models::{enums as api_enums, payments};
+use api_models::{enums as api_enums, gsm as gsm_api_types, payments, routing::ConnectorSelection};
 use common_utils::{
     consts::X_HS_LATENCY,
     crypto::Encryptable,
@@ -8,14 +8,15 @@ use common_utils::{
     pii,
 };
 use diesel_models::enums as storage_enums;
-use error_stack::ResultExt;
+use error_stack::{IntoReport, ResultExt};
+use euclid::enums as dsl_enums;
 use masking::{ExposeInterface, PeekInterface};
 
 use super::domain;
 use crate::{
     core::errors,
     services::authentication::get_header_value_by_key,
-    types::{api as api_types, storage},
+    types::{api as api_types, api::routing as routing_types, storage},
 };
 
 pub trait ForeignInto<T> {
@@ -169,6 +170,154 @@ impl ForeignFrom<storage_enums::MandateDataType> for api_models::payments::Manda
     }
 }
 
+impl ForeignTryFrom<api_enums::Connector> for api_enums::RoutableConnectors {
+    type Error = error_stack::Report<common_utils::errors::ValidationError>;
+
+    fn foreign_try_from(from: api_enums::Connector) -> Result<Self, Self::Error> {
+        Ok(match from {
+            #[cfg(feature = "dummy_connector")]
+            api_enums::Connector::DummyConnector1 => Self::DummyConnector1,
+            #[cfg(feature = "dummy_connector")]
+            api_enums::Connector::DummyConnector2 => Self::DummyConnector2,
+            #[cfg(feature = "dummy_connector")]
+            api_enums::Connector::DummyConnector3 => Self::DummyConnector3,
+            #[cfg(feature = "dummy_connector")]
+            api_enums::Connector::DummyConnector4 => Self::DummyConnector4,
+            #[cfg(feature = "dummy_connector")]
+            api_enums::Connector::DummyConnector5 => Self::DummyConnector5,
+            #[cfg(feature = "dummy_connector")]
+            api_enums::Connector::DummyConnector6 => Self::DummyConnector6,
+            #[cfg(feature = "dummy_connector")]
+            api_enums::Connector::DummyConnector7 => Self::DummyConnector7,
+            api_enums::Connector::Aci => Self::Aci,
+            api_enums::Connector::Adyen => Self::Adyen,
+            api_enums::Connector::Airwallex => Self::Airwallex,
+            api_enums::Connector::Authorizedotnet => Self::Authorizedotnet,
+            api_enums::Connector::Bitpay => Self::Bitpay,
+            api_enums::Connector::Bambora => Self::Bambora,
+            api_enums::Connector::Bluesnap => Self::Bluesnap,
+            api_enums::Connector::Boku => Self::Boku,
+            api_enums::Connector::Braintree => Self::Braintree,
+            api_enums::Connector::Cashtocode => Self::Cashtocode,
+            api_enums::Connector::Checkout => Self::Checkout,
+            api_enums::Connector::Coinbase => Self::Coinbase,
+            api_enums::Connector::Cryptopay => Self::Cryptopay,
+            api_enums::Connector::Cybersource => Self::Cybersource,
+            api_enums::Connector::Dlocal => Self::Dlocal,
+            api_enums::Connector::Fiserv => Self::Fiserv,
+            api_enums::Connector::Forte => Self::Forte,
+            api_enums::Connector::Globalpay => Self::Globalpay,
+            api_enums::Connector::Globepay => Self::Globepay,
+            api_enums::Connector::Gocardless => Self::Gocardless,
+            api_enums::Connector::Helcim => Self::Helcim,
+            api_enums::Connector::Iatapay => Self::Iatapay,
+            api_enums::Connector::Klarna => Self::Klarna,
+            api_enums::Connector::Mollie => Self::Mollie,
+            api_enums::Connector::Multisafepay => Self::Multisafepay,
+            api_enums::Connector::Nexinets => Self::Nexinets,
+            api_enums::Connector::Nmi => Self::Nmi,
+            api_enums::Connector::Noon => Self::Noon,
+            api_enums::Connector::Nuvei => Self::Nuvei,
+            api_enums::Connector::Opennode => Self::Opennode,
+            api_enums::Connector::Payme => Self::Payme,
+            api_enums::Connector::Paypal => Self::Paypal,
+            api_enums::Connector::Payu => Self::Payu,
+            api_enums::Connector::Plaid => {
+                Err(common_utils::errors::ValidationError::InvalidValue {
+                    message: "plaid is not a routable connector".to_string(),
+                })
+                .into_report()?
+            }
+            api_enums::Connector::Powertranz => Self::Powertranz,
+            api_enums::Connector::Rapyd => Self::Rapyd,
+            api_enums::Connector::Shift4 => Self::Shift4,
+            api_enums::Connector::Signifyd => {
+                Err(common_utils::errors::ValidationError::InvalidValue {
+                    message: "signifyd is not a routable connector".to_string(),
+                })
+                .into_report()?
+            }
+            api_enums::Connector::Square => Self::Square,
+            api_enums::Connector::Stax => Self::Stax,
+            api_enums::Connector::Stripe => Self::Stripe,
+            api_enums::Connector::Trustpay => Self::Trustpay,
+            api_enums::Connector::Tsys => Self::Tsys,
+            api_enums::Connector::Volt => Self::Volt,
+            api_enums::Connector::Wise => Self::Wise,
+            api_enums::Connector::Worldline => Self::Worldline,
+            api_enums::Connector::Worldpay => Self::Worldpay,
+            api_enums::Connector::Zen => Self::Zen,
+        })
+    }
+}
+
+impl ForeignFrom<dsl_enums::Connector> for api_enums::RoutableConnectors {
+    fn foreign_from(from: dsl_enums::Connector) -> Self {
+        match from {
+            #[cfg(feature = "dummy_connector")]
+            dsl_enums::Connector::DummyConnector1 => Self::DummyConnector1,
+            #[cfg(feature = "dummy_connector")]
+            dsl_enums::Connector::DummyConnector2 => Self::DummyConnector2,
+            #[cfg(feature = "dummy_connector")]
+            dsl_enums::Connector::DummyConnector3 => Self::DummyConnector3,
+            #[cfg(feature = "dummy_connector")]
+            dsl_enums::Connector::DummyConnector4 => Self::DummyConnector4,
+            #[cfg(feature = "dummy_connector")]
+            dsl_enums::Connector::DummyConnector5 => Self::DummyConnector5,
+            #[cfg(feature = "dummy_connector")]
+            dsl_enums::Connector::DummyConnector6 => Self::DummyConnector6,
+            #[cfg(feature = "dummy_connector")]
+            dsl_enums::Connector::DummyConnector7 => Self::DummyConnector7,
+            dsl_enums::Connector::Aci => Self::Aci,
+            dsl_enums::Connector::Adyen => Self::Adyen,
+            dsl_enums::Connector::Airwallex => Self::Airwallex,
+            dsl_enums::Connector::Authorizedotnet => Self::Authorizedotnet,
+            dsl_enums::Connector::Bitpay => Self::Bitpay,
+            dsl_enums::Connector::Bambora => Self::Bambora,
+            dsl_enums::Connector::Bluesnap => Self::Bluesnap,
+            dsl_enums::Connector::Boku => Self::Boku,
+            dsl_enums::Connector::Braintree => Self::Braintree,
+            dsl_enums::Connector::Cashtocode => Self::Cashtocode,
+            dsl_enums::Connector::Checkout => Self::Checkout,
+            dsl_enums::Connector::Coinbase => Self::Coinbase,
+            dsl_enums::Connector::Cryptopay => Self::Cryptopay,
+            dsl_enums::Connector::Cybersource => Self::Cybersource,
+            dsl_enums::Connector::Dlocal => Self::Dlocal,
+            dsl_enums::Connector::Fiserv => Self::Fiserv,
+            dsl_enums::Connector::Forte => Self::Forte,
+            dsl_enums::Connector::Globalpay => Self::Globalpay,
+            dsl_enums::Connector::Globepay => Self::Globepay,
+            dsl_enums::Connector::Gocardless => Self::Gocardless,
+            dsl_enums::Connector::Helcim => Self::Helcim,
+            dsl_enums::Connector::Iatapay => Self::Iatapay,
+            dsl_enums::Connector::Klarna => Self::Klarna,
+            dsl_enums::Connector::Mollie => Self::Mollie,
+            dsl_enums::Connector::Multisafepay => Self::Multisafepay,
+            dsl_enums::Connector::Nexinets => Self::Nexinets,
+            dsl_enums::Connector::Nmi => Self::Nmi,
+            dsl_enums::Connector::Noon => Self::Noon,
+            dsl_enums::Connector::Nuvei => Self::Nuvei,
+            dsl_enums::Connector::Opennode => Self::Opennode,
+            dsl_enums::Connector::Payme => Self::Payme,
+            dsl_enums::Connector::Paypal => Self::Paypal,
+            dsl_enums::Connector::Payu => Self::Payu,
+            dsl_enums::Connector::Powertranz => Self::Powertranz,
+            dsl_enums::Connector::Rapyd => Self::Rapyd,
+            dsl_enums::Connector::Shift4 => Self::Shift4,
+            dsl_enums::Connector::Square => Self::Square,
+            dsl_enums::Connector::Stax => Self::Stax,
+            dsl_enums::Connector::Stripe => Self::Stripe,
+            dsl_enums::Connector::Trustpay => Self::Trustpay,
+            dsl_enums::Connector::Tsys => Self::Tsys,
+            dsl_enums::Connector::Volt => Self::Volt,
+            dsl_enums::Connector::Wise => Self::Wise,
+            dsl_enums::Connector::Worldline => Self::Worldline,
+            dsl_enums::Connector::Worldpay => Self::Worldpay,
+            dsl_enums::Connector::Zen => Self::Zen,
+        }
+    }
+}
+
 impl ForeignFrom<storage_enums::MandateAmountData> for api_models::payments::MandateAmountData {
     fn foreign_from(from: storage_enums::MandateAmountData) -> Self {
         Self {
@@ -862,3 +1011,40 @@ impl From<domain::Address> for payments::AddressDetails {
         }
     }
 }
+
+impl ForeignFrom<ConnectorSelection> for routing_types::RoutingAlgorithm {
+    fn foreign_from(value: ConnectorSelection) -> Self {
+        match value {
+            ConnectorSelection::Priority(connectors) => Self::Priority(connectors),
+
+            ConnectorSelection::VolumeSplit(splits) => Self::VolumeSplit(splits),
+        }
+    }
+}
+
+impl ForeignFrom<api_models::organization::OrganizationNew>
+    for diesel_models::organization::OrganizationNew
+{
+    fn foreign_from(item: api_models::organization::OrganizationNew) -> Self {
+        Self {
+            org_id: item.org_id,
+            org_name: item.org_name,
+        }
+    }
+}
+
+impl ForeignFrom<gsm_api_types::GsmCreateRequest> for storage::GatewayStatusMappingNew {
+    fn foreign_from(value: gsm_api_types::GsmCreateRequest) -> Self {
+        Self {
+            connector: value.connector.to_string(),
+            flow: value.flow,
+            sub_flow: value.sub_flow,
+            code: value.code,
+            message: value.message,
+            decision: value.decision.to_string(),
+            status: value.status,
+            router_error: value.router_error,
+            step_up_possible: value.step_up_possible,
+        }
+    }
+}
diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs
index 0f5fbeb46553..4933b4d700d3 100644
--- a/crates/router/src/utils.rs
+++ b/crates/router/src/utils.rs
@@ -1,6 +1,8 @@
 pub mod custom_serde;
 pub mod db_utils;
 pub mod ext_traits;
+#[cfg(feature = "olap")]
+pub mod user;
 
 #[cfg(feature = "kv_store")]
 pub mod storage_partitioning;
@@ -401,6 +403,7 @@ pub fn handle_json_response_deserialization_failure(
                 code: consts::NO_ERROR_CODE.to_string(),
                 message: consts::UNSUPPORTED_ERROR_MESSAGE.to_string(),
                 reason: Some(response_data),
+                attempt_status: None,
             })
         }
     }
@@ -566,7 +569,7 @@ impl CustomerAddress for api_models::customers::CustomerRequest {
                     .async_lift(|inner| encrypt_optional(inner, key))
                     .await?,
                 country_code: self.phone_country_code.clone(),
-                customer_id: customer_id.to_string(),
+                customer_id: Some(customer_id.to_string()),
                 merchant_id: merchant_id.to_string(),
                 address_id: generate_id(consts::ID_LENGTH, "add"),
                 payment_id: None,
@@ -699,6 +702,7 @@ impl ForeignTryFrom<enums::IntentStatus> for enums::EventType {
 
 pub async fn trigger_payments_webhook<F, Req, Op>(
     merchant_account: domain::MerchantAccount,
+    business_profile: diesel_models::business_profile::BusinessProfile,
     payment_data: crate::core::payments::PaymentData<F>,
     req: Option<Req>,
     customer: Option<domain::Customer>,
@@ -749,10 +753,13 @@ where
         if let services::ApplicationResponse::JsonWithHeaders((payments_response_json, _)) =
             payments_response
         {
+            let m_state = state.clone();
+
             Box::pin(
                 webhooks_core::create_event_and_trigger_appropriate_outgoing_webhook(
-                    state.clone(),
+                    m_state,
                     merchant_account,
+                    business_profile,
                     event_type,
                     diesel_models::enums::EventClass::Payments,
                     None,
@@ -767,3 +774,16 @@ where
 
     Ok(())
 }
+
+type Handle<T> = tokio::task::JoinHandle<RouterResult<T>>;
+
+pub async fn flatten_join_error<T>(handle: Handle<T>) -> RouterResult<T> {
+    match handle.await {
+        Ok(Ok(t)) => Ok(t),
+        Ok(Err(err)) => Err(err),
+        Err(err) => Err(err)
+            .into_report()
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Join Error"),
+    }
+}
diff --git a/crates/router/src/utils/custom_serde.rs b/crates/router/src/utils/custom_serde.rs
index 8b137891791f..dcdad3092b2f 100644
--- a/crates/router/src/utils/custom_serde.rs
+++ b/crates/router/src/utils/custom_serde.rs
@@ -1 +1,7 @@
-
+pub fn display_serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
+where
+    T: std::fmt::Display,
+    S: serde::ser::Serializer,
+{
+    serializer.serialize_str(&format!("{}", value))
+}
diff --git a/crates/router/src/utils/user.rs b/crates/router/src/utils/user.rs
new file mode 100644
index 000000000000..c72e4b9feb3c
--- /dev/null
+++ b/crates/router/src/utils/user.rs
@@ -0,0 +1 @@
+pub mod password;
diff --git a/crates/router/src/utils/user/blocker_emails.txt b/crates/router/src/utils/user/blocker_emails.txt
new file mode 100644
index 000000000000..e29e1b2d86f4
--- /dev/null
+++ b/crates/router/src/utils/user/blocker_emails.txt
@@ -0,0 +1,2349 @@
+020.co.uk
+123.com
+123box.net
+123india.com
+123mail.cl
+123mail.org
+123qwe.co.uk
+138mail.com
+141.ro
+150mail.com
+150ml.com
+16mail.com
+1963chevrolet.com
+1963pontiac.com
+1netdrive.com
+1st-website.com
+1stpd.net
+2-mail.com
+20after4.com
+21cn.com
+24h.co.jp
+24horas.com
+271soundview.com
+2die4.com
+2mydns.com
+2net.us
+3000.it
+3ammagazine.com
+3email.com
+3xl.net
+444.net
+4email.com
+4email.net
+4newyork.com
+50mail.com
+55mail.cc
+5fm.za.com
+6210.hu
+6sens.com
+702mail.co.za
+7110.hu
+8848.net
+8m.com
+8m.net
+8x.com.br
+8u8.com
+8u8.hk
+8u8.tw
+a-topmail.at
+about.com
+abv.bg
+acceso.or.cr
+access4less.net
+accessgcc.com
+acmemail.net
+adiga.com
+adinet.com.uy
+adres.nl
+advalvas.be
+aeiou.pt
+aeneasmail.com
+afrik.com
+afropoets.com
+aggies.com
+ahaa.dk
+aichi.com
+aim.com
+airpost.net
+aiutamici.com
+aklan.com
+aknet.kg
+alabama.usa.com
+alaska.usa.com
+alavatotal.com
+albafind.com
+albawaba.com
+alburaq.net
+aldeax.com
+aldeax.com.ar
+alex4all.com
+aliyun.com
+alexandria.cc
+algeria.com
+alice.it
+allmail.net
+alskens.dk
+altavista.se
+altbox.org
+alternativagratis.com
+alum.com
+alunos.unipar.br
+alvilag.hu
+amenworld.com
+america.hm
+americamail.com
+amnetsal.com
+amorous.com
+ananzi.co.za
+anet.ne.jp
+anfmail.com
+angelfire.com
+animail.net
+aniverse.com
+anjungcafe.com
+another.com
+antedoonsub.com
+antwerpen.com
+anunciador.net
+anytimenow.com
+aon.at
+apexmail.com
+apollo.lv
+approvers.net
+aprava.com
+apropo.ro
+arcor.de
+argentina.com
+arizona.usa.com
+arkansas.usa.com
+armmail.com
+army.com
+arnet.com.ar
+aroma.com
+arrl.net
+aruba.it
+asheville.com
+asia-links.com
+asiamail.com
+assala.com
+assamesemail.com
+asurfer.com
+atl.lv
+atlas.cz
+atlas.sk
+atozasia.com
+atreillou.com
+att.net
+au.ru
+aubenin.com
+aus-city.com
+aussiemail.com.au
+avasmail.com.mv
+axarnet.com
+ayna.com
+azet.sk
+babbalu.com
+badgers.com
+bakpaka.com
+bakpaka.net
+balochistan.org
+baluch.com
+bama-fan.com
+bancora.net
+bankersmail.com
+barlick.net
+beeebank.com
+beehive.org
+been-there.com
+beirut.com
+belizehome.com
+belizemail.net
+belizeweb.com
+bellsouth.net
+berlin.de
+bestmail.us
+bflomail.com
+bgnmail.com
+bharatmail.com
+big-orange.com
+bigboss.cz
+bigfoot.com
+bigger.com
+bigmailbox.com
+bigmir.net
+bigstring.com
+bip.net
+bigpond.com
+bitwiser.com
+biz.by
+bizhosting.com
+black-sea.ro
+blackburnmail.com
+blackglobalnetwork.net
+blink182.net
+blue.devils.com
+bluebottle.com
+bluemail.ch
+blumail.org
+blvds.com
+bol.com.br
+bolando.com
+bollywood2000.com
+bollywoodz.com
+bombka.dyn.pl
+bonbon.net
+boom.com
+bootmail.com
+bostonoffice.com
+box.az
+boxbg.com
+boxemail.com
+brain.com.pk
+brasilia.net
+bravanese.com
+brazilmail.com.br
+breathe.com
+brestonline.com
+brfree.com.br
+brujula.net
+btcc.org
+buffaloes.com
+bulgaria.com
+bulldogs.com
+bumerang.ro
+burntmail.com
+butch-femme.net
+buzy.com
+buzzjakkerz.com
+c-box.cz
+c3.hu
+c4.com
+cadinfo.net
+calcfacil.com.br
+calcware.org
+california.usa.com
+callnetuk.com
+camaroclubsweden.com
+canada-11.com
+canada.com
+canal21.com
+canoemail.com
+caramail.com
+cardblvd.com
+care-mail.com
+care2.com
+caress.com
+carioca.net
+cashette.com
+casino.com
+casinomail.com
+cataloniamail.com
+catalunyamail.com
+cataz.com
+catcha.com
+catholic.org
+caths.co.uk
+caxess.net
+cbrmail.com
+cc.lv
+cemelli.com
+centoper.it
+centralpets.com
+centrum.cz
+centrum.sk
+centurylink.net
+cercaziende.it
+cgac.es
+chaiyo.com
+chaiyomail.com
+chance2mail.com
+channelonetv.com
+charter.net
+chattown.com
+checkitmail.at
+chelny.com
+cheshiremail.com
+chil-e.com
+chillimail.com
+china.com
+christianmail.org
+ciaoweb.it
+cine.com
+ciphercom.net
+circlemail.com
+cititrustbank1.cjb.net
+citromail.hu
+citynetusa.com
+ciudad.com.ar
+claramail.com
+classicmail.co.za
+cliffhanger.com
+clix.pt
+close2you.net
+cluemail.com
+clujnapoca.ro
+collegeclub.com
+colombia.com
+colorado.usa.com
+comcast.net
+comfortable.com
+compaqnet.fr
+compuserve.com
+computer.net
+computermail.net
+computhouse.com
+conevyt.org.mx
+connect4free.net
+connecticut.usa.com
+coolgoose.com
+coolkiwi.com
+coollist.com
+coxinet.net
+coolmail.com
+coolmail.net
+coolsend.com
+cooltoad.com
+cooperation.net
+copacabana.com
+copticmail.com
+corporateattorneys.com
+corporation.net
+correios.net.br
+correomagico.com
+cosmo.com
+cosmosurf.net
+cougars.com
+count.com
+countrybass.com
+couple.com
+criticalpath.net
+critterpost.com
+crosspaths.net
+crosswinds.net
+cryingmail.com
+cs.com
+csucsposta.hu
+cumbriamail.com
+curio-city.com
+custmail.com
+cwazy.co.uk
+cwazy.net
+cww.de
+cyberaccess.com.pk
+cybergirls.dk
+cyberguys.dk
+cybernet.it
+cymail.net
+dabsol.net
+dada.net
+dadanet.it
+dailypioneer.com
+damuc.org.br
+dansegulvet.com
+darkhorsefan.net
+data54.com
+davegracey.com
+dayzers.com
+daum.net
+dbmail.com
+dcemail.com
+dcsi.net
+deacons.com
+deadlymob.org
+deal-maker.com
+dearriba.com
+degoo.com
+delajaonline.org
+delaware.usa.com
+delfi.lv
+delhimail.com
+demon.deacons.com
+desertonline.com
+desidrivers.com
+deskpilot.com
+despammed.com
+detik.com
+devils.com
+dexara.net
+dhmail.net
+di-ve.com
+didamail.com
+digitaltrue.com
+direccion.com
+director-general.com
+diri.com
+discardmail.com
+discoverymail.net
+disinfo.net
+djmillenium.com
+dmailman.com
+dnsmadeeasy.com
+do.net.ar
+dodgeit.com
+dogmail.co.uk
+doityourself.com
+domaindiscover.com
+domainmanager.com
+doneasy.com
+dontexist.org
+dores.com
+dostmail.com
+dot5hosting.com
+dotcom.fr
+dotnow.com
+dott.it
+doubt.com
+dplanet.ch
+dragoncon.net
+dragonfans.com
+dropzone.com
+dserver.org
+dubaiwebcity.com
+dublin.ie
+dustdevil.com
+dynamitemail.com
+dyndns.org
+e-apollo.lv
+e-hkma.com
+e-mail.cz
+e-mail.ph
+e-mailanywhere.com
+e-milio.com
+e-tapaal.com
+e-webtec.com
+earthalliance.com
+earthling.net
+eastmail.com
+eastrolog.com
+easy-pages.com
+easy.com
+easyinfomail.co.za
+easypeasy.com
+echina.com
+ecn.org
+ecplaza.net
+eircom.net
+edsamail.com.ph
+educacao.te.pt
+edumail.co.za
+eeism.com
+ego.co.th
+ekolay.net
+elforotv.com.ar
+elitemail.org
+elsitio.com
+eltimon.com
+elvis.com
+email.com.br
+email.cz
+email.bg
+email.it
+email.lu
+email.lviv.ua
+email.nu
+email.ro
+email.si
+email2me.com
+emailacc.com
+emailaccount.com
+emailaddresses.com
+emailchoice.com
+emailcorner.net
+emailn.de
+emailengine.net
+emailengine.org
+emailgaul.com
+emailgroups.net
+emailhut.net
+emailpinoy.com
+emailplanet.com
+emailplus.org
+emailuser.net
+ematic.com
+embarqmail.com
+embroideryforums.com
+eml.cc
+emoka.ro
+emptymail.com
+enel.net
+enelpunto.net
+england.com
+enterate.com.ar
+entryweb.it
+entusiastisk.com
+enusmail.com
+epatra.com
+epix.net
+epomail.com
+epost.de
+eprompter.com
+eqqu.com
+eramail.co.za
+eresmas.com
+eriga.lv
+ertelecom.ru
+esde-s.org
+esfera.cl
+estadao.com.br
+etllao.com
+euromail.net
+euroseek.com
+euskalmail.com
+evafan.com
+everyday.com.kh
+everymail.net
+everyone.net
+execs2k.com
+executivemail.co.za
+expn.com
+ezilon.com
+ezrs.com
+f-m.fm
+facilmail.com
+fadrasha.net
+fadrasha.org
+faithhighway.com
+faithmail.com
+familymailbox.com
+familyroll.com
+familysafeweb.net
+fan.com
+fan.net
+faroweb.com
+fast-email.com
+fast-mail.org
+fastem.com
+fastemail.us
+fastemailer.com
+fastermail.com
+fastest.cc
+fastimap.com
+fastmailbox.net
+fastmessaging.com
+fastwebmail.it
+fawz.net
+fea.st
+federalcontractors.com
+fedxmail.com
+feelings.com
+female.ru
+fepg.net
+ffanet.com
+fiberia.com
+filipinolinks.com
+financesource.com
+findmail.com
+fiscal.net
+flashmail.com
+flipcode.com
+florida.usa.com
+floridagators.com
+fmail.co.uk
+fmailbox.com
+fmgirl.com
+fmguy.com
+fnmail.com
+footballer.com
+foxmail.com
+forfree.at
+forsythmissouri.org
+fortuncity.com
+forum.dk
+free.com.pe
+free.fr
+free.net.nz
+freeaccess.nl
+freegates.be
+freeghana.com
+freehosting.nl
+freei.co.th
+freeler.nl
+freemail.globalsite.com.br
+freemuslim.net
+freenet.de
+freenet.kg
+freeola.net
+freepgs.com
+freesbee.fr
+freeservers.com
+freestart.hu
+freesurf.ch
+freesurf.fr
+freesurf.nl
+freeuk.com
+freeuk.net
+freeweb.it
+freewebemail.com
+freeyellow.com
+frisurf.no
+frontiernet.net
+fsmail.net
+fsnet.co.uk
+ftml.net
+fuelie.org
+fun-greetings-jokes.com
+fun.21cn.com
+fusemail.com
+fut.es
+gala.net
+galmail.co.za
+gamebox.net
+gamecocks.com
+gawab.com
+gay.com
+gaymailbox.com
+gaza.net
+gazeta.pl
+gci.net
+gdi.net
+geeklife.com
+gemari.or.id
+genxemail.com
+geopia.com
+georgia.usa.com
+getmail.no
+ggaweb.ch
+giga4u.de
+gjk.dk
+glay.org
+glendale.net
+globalfree.it
+globomail.com
+globalpinoy.com
+globalsite.com.br
+globalum.com
+globetrotter.net
+go-bama.com
+go-cavs.com
+go-chargers.com
+go-dawgs.com
+go-gators.com
+go-hogs.com
+go-irish.com
+go-spartans.com
+go-tigers.com
+go.aggies.com
+go.air-force.com
+go.badgers.com
+go.big-orange.com
+go.blue.devils.com
+go.buffaloes.com
+go.bulldogs.com
+go.com
+go.cougars.com
+go.dores.com
+go.gamecocks.com
+go.huskies.com
+go.longhorns.com
+go.mustangs.com
+go.rebels.com
+go.ro
+go.ru
+go.terrapins.com
+go.wildcats.com
+go.wolverines.com
+go.yellow-jackets.com
+go2net.com
+go4.it
+gofree.co.uk
+golfemail.com
+goliadtexas.com
+gomail.com.ua
+gonowmail.com
+gonuts4free.com
+googlemail.com
+goplay.com
+gorontalo.net
+gotmail.com
+gotomy.com
+govzone.com
+grad.com
+graffiti.net
+gratisweb.com
+gtechnics.com
+guate.net
+guessmail.com
+gwalla.com
+h-mail.us
+haberx.com
+hailmail.net
+halejob.com
+hamptonroads.com
+handbag.com
+hanmail.net
+happemail.com
+happycounsel.com
+hawaii.com
+hawaii.usa.com
+hayahaya.tg
+hedgeai.com
+heesun.net
+heremail.com
+hetnet.nl
+highveldmail.co.za
+hildebrands.de
+hingis.org
+hispavista.com
+hitmanrecords.com
+hockeyghiaccio.com
+hockeymail.com
+holapuravida.com
+home.no.net
+home.ro
+home.se
+homelocator.com
+homemail.co.za
+homenetmail.com
+homestead.com
+homosexual.net
+hongkong.com
+hong-kong-1.com
+hopthu.com
+hosanna.net
+hot.ee
+hotbot.com
+hotbox.ru
+hotcoolmail.com
+hotdak.com
+hotfire.net
+hotinbox.com
+hotpop.com
+hotvoice.com
+hour.com
+howling.com
+huhmail.com
+humour.com
+hurra.de
+hush.ai
+hush.com
+hushmail.com
+huskies.com
+hutchcity.com
+i-france.com
+i-p.com
+i12.com
+i2828.com
+ibatam.com
+ibest.com.br
+ibizdns.com
+icafe.com
+ice.is
+icestorm.com
+icq.com
+icqmail.com
+icrazy.com
+id.ru
+idaho.usa.com
+idirect.com
+idncafe.com
+ieg.com.br
+iespalomeras.net
+iespana.es
+ifrance.com
+ig.com.br
+ignazio.it
+illinois.usa.com
+ilse.net
+ilse.nl
+imail.ru
+imailbox.com
+imap-mail.com
+imap.cc
+imapmail.org
+imel.org
+in-box.net
+inbox.com
+inbox.ge
+inbox.lv
+inbox.net
+inbox.ru
+in.com
+incamail.com
+indexa.fr
+india.com
+indiamail.com
+indiana.usa.com
+indiatimes.com
+induquimica.org
+inet.com.ua
+infinito.it
+infoapex.com
+infohq.com
+infomail.es
+infomart.or.jp
+infosat.net
+infovia.com.ar
+inicia.es
+inmail.sk
+inmail24.com
+inoutbox.com
+intelnet.net.gt
+intelnett.com
+interblod.com
+interfree.it
+interia.pl
+interlap.com.ar
+intermail.hu
+internet-e-mail.com
+internet-mail.org
+internet.lu
+internetegypt.com
+internetemails.net
+internetkeno.com
+internetmailing.net
+inwind.it
+iobox.com
+iobox.fi
+iol.it
+iol.pt
+iowa.usa.com
+ip3.com
+ipermitmail.com
+iqemail.com
+iquebec.com
+iran.com
+irangate.net
+iscool.net
+islandmama.com
+ismart.net
+isonews2.com
+isonfire.com
+isp9.net
+ispey.com
+itelgua.com
+itloox.com
+itmom.com
+ivenus.com
+iwan-fals.com
+iwon.com
+ixp.net
+japan.com
+jaydemail.com
+jedrzejow.pl
+jetemail.net
+jingjo.net
+jippii.fi
+jmail.co.za
+jojomail.com
+jovem.te.pt
+joymail.com
+jubii.dk
+jubiipost.dk
+jumpy.it
+juno.com
+justemail.net
+justmailz.com
+k.ro
+kaazoo.com
+kabissa.org
+kaixo.com
+kalluritimes.com
+kalpoint.com
+kansas.usa.com
+katamail.com
+kataweb.it
+kayafmmail.co.za
+keko.com.ar
+kentucky.usa.com
+keptprivate.com
+kimo.com
+kiwitown.com
+klik.it
+klikni.cz
+kmtn.ru
+koko.com
+kolozsvar.ro
+kombud.com
+koreanmail.com
+kotaksuratku.info
+krunis.com
+kukamail.com
+kuronowish.com
+kyokodate.com
+kyokofukada.net
+ladymail.cz
+lagoon.nc
+lahaonline.com
+lamalla.net
+lancsmail.com
+land.ru
+laposte.net
+latinmail.com
+lawyer.com
+lawyersmail.com
+lawyerzone.com
+lebanonatlas.com
+leehom.net
+leonardo.it
+leonlai.net
+letsjam.com
+letterbox.org
+letterboxes.org
+levele.com
+lexpress.net
+libero.it
+liberomail.com
+libertysurf.net
+libre.net
+lightwines.org
+linkmaster.com
+linuxfreemail.com
+lionsfan.com.au
+livedoor.com
+llandudno.com
+llangollen.com
+lmxmail.sk
+loggain.net
+loggain.nu
+lolnetwork.net
+london.com
+longhorns.com
+look.com
+looksmart.co.uk
+looksmart.com
+looksmart.com.au
+loteria.net
+lotonazo.com
+louisiana.usa.com
+louiskoo.com
+loveable.com
+lovemail.com
+lovingjesus.com
+lpemail.com
+luckymail.com
+luso.pt
+lusoweb.pt
+luukku.com
+lycosmail.com
+mac.com
+machinecandy.com
+macmail.com
+mad.scientist.com
+madcrazy.com
+madonno.com
+madrid.com
+mag2.com
+magicmail.co.za
+magik-net.com
+mail-atlas.net
+mail-awu.de
+mail-box.cz
+mail.by
+mail-center.com
+mail-central.com
+mail-jp.org
+mail-online.dk
+mail-page.com
+mail-x-change.com
+mail.austria.com
+mail.az
+mail.de
+mail.be
+mail.bg
+mail.bulgaria.com
+mail.co.za
+mail.dk
+mail.ee
+mail.goo.ne.jp
+mail.gr
+mail.lawguru.com
+mail.md
+mail.mn
+mail.org
+mail.pf
+mail.pt
+mail.ru
+mail.yahoo.co.jp
+mail15.com
+mail3000.com
+mail333.com
+mail8.com
+mailandftp.com
+mailandnews.com
+mailas.com
+mailasia.com
+mailbg.com
+mailblocks.com
+mailbolt.com
+mailbox.as
+mailbox.co.za
+mailbox.gr
+mailbox.hu
+mailbox.sk
+mailc.net
+mailcan.com
+mailcircuit.com
+mailclub.fr
+mailclub.net
+maildozy.com
+mailfly.com
+mailforce.net
+mailftp.com
+mailglobal.net
+mailhaven.com
+mailinator.com
+mailingaddress.org
+mailingweb.com
+mailisent.com
+mailite.com
+mailme.dk
+mailmight.com
+mailmij.nl
+mailnew.com
+mailops.com
+mailpanda.com
+mailpersonal.com
+mailroom.com
+mailru.com
+mails.de
+mailsent.net
+mailserver.dk
+mailservice.ms
+mailsnare.net
+mailsurf.com
+mailup.net
+mailvault.com
+mailworks.org
+maine.usa.com
+majorana.martina-franca.ta.it
+maktoob.com
+malayalamtelevision.net
+malayalapathram.com
+male.ru
+manager.de
+manlymail.net
+mantrafreenet.com
+mantramail.com
+mantraonline.com
+marihuana.ro
+marijuana.nl
+marketweighton.com
+maryland.usa.com
+masrawy.com
+massachusetts.usa.com
+mauimail.com
+mbox.com.au
+mcrmail.com
+me.by
+me.com
+medicinatv.com
+meetingmall.com
+megamail.pt
+menara.ma
+merseymail.com
+mesra.net
+messagez.com
+metacrawler.com
+mexico.com
+miaoweb.net
+michigan.usa.com
+micro2media.com
+miesto.sk
+mighty.co.za
+milacamn.net
+milmail.com
+mindless.com
+mindviz.com
+minnesota.usa.com
+mississippi.usa.com
+missouri.usa.com
+mixmail.com
+ml1.net
+ml2clan.com
+mlanime.com
+mm.st
+mmail.com
+mobimail.mn
+mobsters.com
+mobstop.com
+modemnet.net
+modomail.com
+moldova.com
+moldovacc.com
+monarchy.com
+montana.usa.com
+montevideo.com.uy
+moomia.com
+moose-mail.com
+mosaicfx.com
+motormania.com
+movemail.com
+mr.outblaze.com
+mrspender.com
+mscold.com
+msnzone.cn
+mundo-r.com
+muslimsonline.com
+mustangs.com
+mxs.de
+myblue.cc
+mycabin.com
+mycity.com
+mycommail.com
+mycool.com
+mydomain.com
+myeweb.com
+myfastmail.com
+myfunnymail.com
+mygrande.net
+mykolab.com
+mygamingconsoles.com
+myiris.com
+myjazzmail.com
+mymacmail.com
+mymail.dk
+mymail.ph.inter.net
+mymail.ro
+mynet.com
+mynet.com.tr
+myotw.net
+myopera.com
+myownemail.com
+mypersonalemail.com
+myplace.com
+myrealbox.com
+myspace.com
+myt.mu
+myway.com
+mzgchaos.de
+n2.com
+n2business.com
+n2mail.com
+n2software.com
+nabble.com
+name.com
+nameplanet.com
+nanamail.co.il
+nanaseaikawa.com
+nandomail.com
+naseej.com
+nastything.com
+national-champs.com
+nativeweb.net
+narod.ru
+nate.com
+naveganas.com
+naver.com
+nebraska.usa.com
+nemra1.com
+nenter.com
+nerdshack.com
+nervhq.org
+net.hr
+net4b.pt
+net4jesus.com
+net4you.at
+netbounce.com
+netcabo.pt
+netcape.net
+netcourrier.com
+netexecutive.com
+netfirms.com
+netkushi.com
+netmongol.com
+netpiper.com
+netposta.net
+netscape.com
+netscape.net
+netscapeonline.co.uk
+netsquare.com
+nettaxi.com
+netti.fi
+networld.com
+netzero.com
+netzero.net
+neustreet.com
+nevada.usa.com
+newhampshire.usa.com
+newjersey.usa.com
+newmail.com
+newmail.net
+newmail.ok.com
+newmail.ru
+newmexico.usa.com
+newspaperemail.com
+newyork.com
+newyork.usa.com
+newyorkcity.com
+nfmail.com
+nicegal.com
+nightimeuk.com
+nightly.com
+nightmail.com
+nightmail.ru
+noavar.com
+noemail.com
+nonomail.com
+nokiamail.com
+noolhar.com
+northcarolina.usa.com
+northdakota.usa.com
+nospammail.net
+nowzer.com
+ny.com
+nyc.com
+nz11.com
+nzoomail.com
+o2.pl
+oceanfree.net
+ocsnet.net
+oddpost.com
+odeon.pl
+odmail.com
+offshorewebmail.com
+ofir.dk
+ohio.usa.com
+oicexchange.com
+ok.ru
+oklahoma.usa.com
+ole.com
+oleco.net
+olympist.net
+omaninfo.com
+onatoo.com
+ondikoi.com
+onebox.com
+onenet.com.ar
+onet.pl
+ongc.net
+oninet.pt
+online.ie
+online.ru
+onlinewiz.com
+onobox.com
+open.by
+openbg.com
+openforyou.com
+opentransfer.com
+operamail.com
+oplusnet.com
+orange.fr
+orangehome.co.uk
+orange.es
+orange.jo
+orange.pl
+orbitel.bg
+orcon.net.nz
+oregon.usa.com
+oreka.com
+organizer.net
+orgio.net
+orthodox.com
+osite.com.br
+oso.com
+ourbrisbane.com
+ournet.md
+ourprofile.net
+ourwest.com
+outgun.com
+ownmail.net
+oxfoot.com
+ozu.es
+pacer.com
+paginasamarillas.com
+pakistanmail.com
+pandawa.com
+pando.com
+pandora.be
+paris.com
+parsimail.com
+parspage.com
+patmail.com
+pattayacitythailand.com
+pc4me.us
+pcpostal.com
+penguinmaster.com
+pennsylvania.usa.com
+peoplepc.com
+peopleweb.com
+personal.ro
+personales.com
+peru.com
+petml.com
+phreaker.net
+pigeonportal.com
+pilu.com
+pimagop.com
+pinoymail.com
+pipni.cz
+pisem.net
+planet-school.de
+planetaccess.com
+planetout.com
+plasa.com
+playersodds.com
+playful.com
+pluno.com
+plusmail.com.br
+pmail.net
+pnetmail.co.za
+pobox.ru
+pobox.sk
+pochtamt.ru
+pochta.ru
+poczta.fm
+poetic.com
+pogowave.com
+polbox.com
+pop3.ru
+pop.co.th
+popmail.com
+poppymail.com
+popsmail.com
+popstar.com
+portafree.com
+portaldosalunos.com
+portugalmail.com
+portugalmail.pt
+post.cz
+post.expart.ne.jp
+post.pl
+post.sk
+posta.ge
+postaccesslite.com
+postiloota.net
+postinbox.com
+postino.ch
+postino.it
+postmaster.co.uk
+postpro.net
+praize.com
+press.co.jp
+primposta.com
+printesamargareta.ro
+private.21cn.com
+probemail.com
+profesional.com
+profession.freemail.com.br
+proinbox.com
+promessage.com
+prontomail.com
+provincial.net
+publicaccounting.com
+punkass.com
+puppy.com.my
+q.com
+qatar.io
+qlmail.com
+qq.com
+qrio.com
+qsl.net
+qudsmail.com
+queerplaces.com
+quepasa.com
+quick.cz
+quickwebmail.com
+r-o-o-t.com
+r320.hu
+raakim.com
+rbcmail.ru
+racingseat.com
+radicalz.com
+radiojobbank.com
+ragingbull.com
+raisingadaughter.com
+rallye-webmail.com
+rambler.ru
+ranmamail.com
+ravearena.com
+ravemail.co.za
+razormail.com
+real.ro
+realemail.net
+reallyfast.biz
+reallyfast.info
+rebels.com
+recife.net
+recme.net
+rediffmailpro.com
+redseven.de
+redwhitearmy.com
+relia.com
+revenue.com
+rexian.com
+rhodeisland.usa.com
+ritmes.net
+rn.com
+roanokemail.com
+rochester-mail.com
+rock.com
+rocketmail.com
+rockfan.com
+rockinghamgateway.com
+rojname.com
+rol.ro
+rollin.com
+rome.com
+romymichele.com
+royal.net
+rpharmacist.com
+rt.nl
+ru.ru
+rushpost.com
+russiamail.com
+rxpost.net
+s-mail.com
+saabnet.com
+sacbeemail.com
+sacmail.com
+safe-mail.net
+safe-mailbox.com
+saigonnet.vn
+saint-mike.org
+samilan.net
+sandiego.com
+sanook.com
+sanriotown.com
+sapibon.com
+sapo.pt
+saturnfans.com
+sayhi.net
+sbcglobal.com
+scfn.net
+schweiz.org
+sci.fi
+sciaga.pl
+scrapbookscrapbook.com
+seapole.com
+search417.com
+seark.com
+sebil.com
+secretservices.net
+secure-jlnet.com
+seductive.com
+sendmail.ru
+sendme.cz
+sent.as
+sent.at
+sent.com
+serga.com.ar
+sermix.com
+server4free.de
+serverwench.com
+sesmail.com
+sexmagnet.com
+seznam.cz
+shadango.com
+she.com
+shuf.com
+siamlocalhost.com
+siamnow.net
+sify.com
+sinamail.com
+singapore.com
+singmail.com
+singnet.com.sg
+siraj.org
+sirindia.com
+sirunet.com
+sister.com
+sina.com
+sina.cn
+sinanail.com
+sistersbrothers.com
+sizzling.com
+slamdunkfan.com
+slickriffs.co.uk
+slingshot.com
+slo.net
+slomusic.net
+smartemail.co.uk
+smtp.ru
+snail-mail.net
+sndt.net
+sneakemail.com
+snoopymail.com
+snowboarding.com
+so-simple.org
+socamail.com
+softhome.net
+sohu.com
+sol.dk
+solidmail.com
+soon.com
+sos.lv
+soundvillage.org
+southcarolina.usa.com
+southdakota.usa.com
+space.com
+spacetowns.com
+spamex.com
+spartapiet.com
+speed-racer.com
+speedpost.net
+speedymail.org
+spils.com
+spinfinder.com
+sportemail.com
+spray.net
+spray.no
+spray.se
+spymac.com
+srbbs.com
+srilankan.net
+ssan.com
+ssl-mail.com
+stade.fr
+stalag13.com
+stampmail.com
+starbuzz.com
+starline.ee
+starmail.com
+starmail.org
+starmedia.com
+starspath.com
+start.com.au
+start.no
+stribmail.com
+student.com
+student.ednet.ns.ca
+studmail.com
+sudanmail.net
+suisse.org
+sunbella.net
+sunmail1.com
+sunpoint.net
+sunrise.ch
+sunumail.sn
+sunuweb.net
+suomi24.fi
+superdada.it
+supereva.com
+supereva.it
+supermailbox.com
+superposta.com
+surf3.net
+surfassistant.com
+surfsupnet.net
+surfy.net
+surimail.com
+surnet.cl
+sverige.nu
+svizzera.org
+sweb.cz
+swift-mail.com
+swissinfo.org
+swissmail.net
+switzerland.org
+syom.com
+syriamail.com
+t-mail.com
+t-net.net.ve
+t2mail.com
+tabasheer.com
+talk21.com
+talkcity.com
+tangmonkey.com
+tatanova.com
+taxcutadvice.com
+techemail.com
+technisamail.co.za
+teenmail.co.uk
+teenmail.co.za
+tejary.com
+telebot.com
+telefonica.net
+telegraf.by
+teleline.es
+telinco.net
+telkom.net
+telpage.net
+telstra.com
+telenet.be
+telusplanet.net
+tempting.com
+tenchiclub.com
+tennessee.usa.com
+terrapins.com
+texas.usa.com
+texascrossroads.com
+tfz.net
+thai.com
+thaimail.com
+thaimail.net
+the-fastest.net
+the-quickest.com
+thegame.com
+theinternetemail.com
+theoffice.net
+thepostmaster.net
+theracetrack.com
+theserverbiz.com
+thewatercooler.com
+thewebpros.co.uk
+thinkpost.net
+thirdage.com
+thundermail.com
+tim.it
+timemail.com
+tin.it
+tinati.net
+tiscalinet.it
+tjohoo.se
+tkcity.com
+tlcfan.com
+tlen.pl
+tmicha.net
+todito.com
+todoperros.com
+tokyo.com
+topchat.com
+topmail.com.ar
+topmail.dk
+topmail.co.ie
+topmail.co.in
+topmail.co.nz
+topmail.co.uk
+topmail.co.za
+topsurf.com
+toquedequeda.com
+torba.com
+torchmail.com
+totalmail.com
+totalsurf.com
+totonline.net
+tough.com
+toughguy.net
+trav.se
+trevas.net
+tripod-mail.com
+triton.net
+trmailbox.com
+tsamail.co.za
+turbonett.com
+turkey.com
+tvnet.lv
+twc.com
+typemail.com
+u2club.com
+uae.ac
+ubbi.com
+ubbi.com.br
+uboot.com
+ugeek.com
+uk2.net
+uk2net.com
+ukr.net
+ukrpost.net
+ukrpost.ua
+uku.co.uk
+ulimit.com
+ummah.org
+unbounded.com
+unicum.de
+unimail.mn
+unitedemailsystems.com
+universal.pt
+universia.cl
+universia.edu.ve
+universia.es
+universia.net.co
+universia.net.mx
+universia.pr
+universia.pt
+universiabrasil.net
+unofree.it
+uol.com.ar
+uol.com.br
+uole.com
+uolmail.com
+uomail.com
+uraniomail.com
+urbi.com.br
+ureach.com
+usanetmail.com
+userbeam.com
+utah.usa.com
+uyuyuy.com
+v-sexi.com
+v3mail.com
+valanides.com
+vegetarisme.be
+velnet.com
+velocall.com
+vercorreo.com
+verizonmail.com
+vermont.usa.com
+verticalheaven.com
+veryfast.biz
+veryspeedy.net
+vfemail.net
+vietmedia.com
+vip.gr
+virgilio.it
+virgin.net
+virginia.usa.com
+virtual-mail.com
+visitmail.com
+visto.com
+vivelared.com
+vjtimail.com
+vnn.vn
+vsnl.com
+vsnl.net
+vodamail.co.za
+voila.fr
+volkermord.com
+vosforums.com
+w.cn
+walla.com
+walla.co.il
+wallet.com
+wam.co.za
+wanex.ge
+wap.hu
+wapda.com
+wapicode.com
+wappi.com
+warpmail.net
+washington.usa.com
+wassup.com
+waterloo.com
+waumail.com
+wazmail.com
+wearab.net
+web-mail.com.ar
+web.de
+web.nl
+web2mail.com
+webaddressbook.com
+webbworks.com
+webcity.ca
+webdream.com
+webemaillist.com
+webindia123.com
+webinfo.fi
+webjump.com
+webl-3.br.inter.net
+webmail.co.yu
+webmail.co.za
+webmails.com
+webmailv.com
+webpim.cc
+webspawner.com
+webstation.com
+websurfer.co.za
+webtopmail.com
+webtribe.net
+webtv.net
+weedmail.com
+weekonline.com
+weirdness.com
+westvirginia.usa.com
+whale-mail.com
+whipmail.com
+who.net
+whoever.com
+wildcats.com
+wildmail.com
+williams.net.ar
+winning.com
+winningteam.com
+winwinhosting.com
+wisconsin.usa.com
+witelcom.com
+witty.com
+wolverines.com
+wooow.it
+workmail.co.za
+worldcrossing.com
+worldemail.com
+worldmedic.com
+worldonline.de
+wowmail.com
+wp.pl
+wprost.pl
+wrongmail.com
+wtonetwork.com
+wurtele.net
+www.com
+www.consulcredit.it
+wyoming.usa.com
+x-mail.net
+xasa.com
+xfreehosting.com
+xmail.net
+xmsg.com
+xnmsn.cn
+xoom.com
+xtra.co.nz
+xuite.net
+xpectmore.com
+xrea.com
+xsmail.com
+xzapmail.com
+y7mail.com
+yahala.co.il
+yaho.com
+yalla.com.lb
+ya.com
+yeah.net
+ya.ru
+yahoomail.com
+yam.com
+yamal.info
+yapost.com
+yawmail.com
+yebox.com
+yehey.com
+yellow-jackets.com
+yellowstone.net
+yenimail.com
+yepmail.net
+yifan.net
+yopmail.com
+your-mail.com
+yours.com
+yourwap.com
+yyhmail.com
+z11.com
+z6.com
+zednet.co.uk
+zeeman.nl
+ziplip.com
+zipmail.com.br
+zipmax.com
+zmail.pt
+zmail.ru
+zona-andina.net
+zonai.com
+zoneview.net
+zonnet.nl
+zoho.com
+zoomshare.com
+zoznam.sk
+zubee.com
+zuvio.com
+zwallet.com
+zworg.com
+zybermail.com
+zzn.com
+126.com
+139.com
+163.com
+188.com
+189.cn
+263.net
+9.cn
+vip.126.com
+vip.163.com
+vip.188.com
+vip.sina.com
+vip.sohu.com
+vip.sohu.net
+vip.tom.com
+vip.qq.com
+vipsohu.net
+clovermail.net
+mail-on.us
+chewiemail.com
+offcolormail.com
+powdermail.com
+tightmail.com
+toothandmail.com
+tushmail.com
+openmail.cc
+expressmail.dk
+4xn.de
+5x2.de
+5x2.me
+aufdrogen.de
+auf-steroide.de
+besser-als-du.de
+brainsurfer.de
+chillaxer.de
+cyberkriminell.de
+danneben.so
+freemailen.de
+freemailn.de
+ist-der-mann.de
+ist-der-wahnsinn.de
+ist-echt.so
+istecht.so
+ist-genialer.de
+ist-schlauer.de
+ist-supersexy.de
+kann.so
+mag-spam.net
+mega-schlau.de
+muss.so
+nerd4life.de
+ohne-drogen-gehts.net
+on-steroids.de
+scheint.so
+staatsterrorist.de
+super-gerissen.de
+unendlich-schlau.de
+vip-client.de
+will-keinen-spam.de
+zu-geil.de
+rbox.me
+rbox.co
+tunome.com
+acatperson.com
+adogperson.com
+all4theskins.com
+allsportsrock.com
+alwaysgrilling.com
+alwaysinthekitchen.com
+alwayswatchingmovies.com
+alwayswatchingtv.com
+asylum.com
+basketball-email.com
+beabookworm.com
+beagolfer.com
+beahealthnut.com
+believeinliberty.com
+bestcoolcars.com
+bestjobcandidate.com
+besure2vote.com
+bigtimecatperson.com
+bigtimedogperson.com
+bigtimereader.com
+bigtimesportsfan.com
+blackvoices.com
+capsfanatic.com
+capshockeyfan.com
+capsred.com
+car-nut.net
+cat-person.com
+catpeoplerule.com
+chat-with-me.com
+cheatasrule.com
+crazy4baseball.com
+crazy4homeimprovement.com
+crazy4mail.com
+crazyaboutfilms.net
+crazycarfan.com
+crazyforemail.com
+crazymoviefan.com
+descriptivemail.com
+differentmail.com
+dog-person.com
+dogpeoplerule.com
+easydoesit.com
+expertrenovator.com
+expressivemail.com
+fanaticos.com
+fanofbooks.com
+fanofcomputers.com
+fanofcooking.com
+fanoftheweb.com
+fieldmail.com
+fleetmail.com
+focusedonprofits.com
+focusedonreturns.com
+futboladdict.com
+games.com
+getintobooks.com
+hail2theskins.com
+hitthepuck.com
+i-dig-movies.com
+i-love-restaurants.com
+idigcomputers.com
+idigelectronics.com
+idigvideos.com
+ilike2helpothers.com
+ilike2invest.com
+ilike2workout.com
+ilikeelectronics.com
+ilikeworkingout.com
+ilovehomeprojects.com
+iloveourteam.com
+iloveworkingout.com
+in2autos.net
+interestedinthejob.com
+intomotors.com
+iwatchrealitytv.com
+lemondrop.com
+love2exercise.com
+love2workout.com
+lovefantasysports.com
+lovetoexercise.com
+luvfishing.com
+luvgolfing.com
+luvsoccer.com
+mail4me.com
+majorgolfer.com
+majorshopaholic.com
+majortechie.com
+mcom.com
+motor-nut.com
+moviefan.com
+mycapitalsmail.com
+mycatiscool.com
+myfantasyteamrules.com
+myteamisbest.com
+netbusiness.com
+news-fanatic.com
+newspaperfan.com
+onlinevideosrock.com
+realbookfan.com
+realhealthnut.com
+realitytvaddict.net
+realitytvnut.com
+reallyintomusic.com
+realtravelfan.com
+redskinscheer.com
+redskinsfamily.com
+redskinsfancentral.com
+redskinshog.com
+redskinsrule.com
+redskinsspecialteams.com
+redskinsultimatefan.com
+scoutmail.com
+skins4life.com
+stargate2.com
+stargateatlantis.com
+stargatefanclub.com
+stargatesg1.com
+stargateu.com
+switched.com
+t-online.de
+thegamefanatic.com
+total-techie.com
+totalfoodnut.com
+totally-into-cooking.com
+totallyintobaseball.com
+totallyintobasketball.com
+totallyintocooking.com
+totallyintofootball.com
+totallyintogolf.com
+totallyintohockey.com
+totallyintomusic.com
+totallyintoreading.com
+totallyintosports.com
+totallyintotravel.com
+totalmoviefan.com
+travel2newplaces.com
+tvchannelsurfer.com
+ultimateredskinsfan.com
+videogamesrock.com
+volunteeringisawesome.com
+wayintocomputers.com
+whatmail.com
+when.com
+wild4music.com
+wildaboutelectronics.com
+workingaroundthehouse.com
+workingonthehouse.com
+writesoon.com
+xmasmail.com
+arab.ir
+denmark.ir
+egypt.ir
+icq.ir
+ir.ae
+iraq.ir
+ire.ir
+ireland.ir
+irr.ir
+jpg.ir
+ksa.ir
+kuwait.ir
+london.ir
+paltalk.ir
+spain.ir
+sweden.ir
+tokyo.ir
+111mail.com
+123iran.com
+37.com
+420email.com
+4degreez.com
+4-music-today.com
+actingbiz.com
+allhiphop.com
+anatomicrock.com
+animeone.com
+asiancutes.com
+a-teens.net
+ausi.com
+autoindia.com
+autopm.com
+barriolife.com
+b-boy.com
+beautifulboy.com
+bgay.com
+bicycledata.com
+bicycling.com
+bigheavyworld.com
+bigmailbox.net
+bikerheaven.net
+bikermail.com
+billssite.com
+blackandchristian.com
+blackcity.net
+blackvault.com
+bmxtrix.com
+boarderzone.com
+boatnerd.com
+bolbox.com
+bongmail.com
+bowl.com
+butch-femme.org
+byke.com
+calle22.com
+cannabismail.com
+catlovers.com
+certifiedbitches.com
+championboxing.com
+chatway.com
+chillymail.com
+classprod.com
+classycouples.com
+congiu.net
+coolshit.com
+corpusmail.com
+cyberunlimited.org
+cycledata.com
+darkfear.com
+darkforces.com
+dirtythird.com
+dopefiends.com
+draac.com
+drakmail.net
+dr-dre.com
+dreamstop.com
+egypt.net
+emailfast.com
+envirocitizen.com
+escapeartist.com
+ezsweeps.com
+famous.as
+farts.com
+feelingnaughty.com
+firemyst.com
+freeonline.com
+fudge.com
+funkytimes.com
+gamerssolution.com
+gazabo.net
+glittergrrrls.com
+goatrance.com
+goddess.com
+gohip.com
+gospelcity.com
+gothicgirl.com
+grapemail.net
+greatautos.org
+guy.com
+haitisurf.com
+happyhippo.com
+hateinthebox.com
+houseofhorrors.com
+hugkiss.com
+hullnumber.com
+idunno4recipes.com
+ihatenetscape.com
+intimatefire.com
+irow.com
+jazzemail.com
+juanitabynum.com
+kanoodle.com
+kickboxing.com
+kidrock.com
+kinkyemail.com
+kool-things.com
+latinabarbie.com
+latinogreeks.com
+leesville.com
+loveemail.com
+lowrider.com
+lucky7lotto.net
+madeniggaz.net
+mailbomb.com
+marillion.net
+megarave.com
+mofa.com
+motley.com
+music.com
+musician.net
+musicsites.com
+netbroadcaster.com
+netfingers.com
+net-surf.com
+nocharge.com
+operationivy.com
+paidoffers.net
+pcbee.com
+persian.com
+petrofind.com
+phunkybitches.com
+pikaguam.com
+pinkcity.net
+pitbullmail.com
+planetsmeg.com
+poop.com
+poormail.com
+potsmokersnet.com
+primetap.com
+project420.com
+prolife.net
+puertoricowow.com
+puppetweb.com
+rapstar.com
+rapworld.com
+rastamall.com
+ratedx.net
+ravermail.com
+relapsecult.com
+remixer.com
+rockeros.com
+romance106fm.com
+singalongcenter.com
+sketchyfriends.com
+slayerized.com
+smartstocks.com
+soulja-beatz.org
+specialoperations.com
+speedymail.net
+spells.com
+superbikeclub.com
+superintendents.net
+surfguiden.com
+sweetwishes.com
+tattoodesign.com
+teamster.net
+teenchatnow.com
+the5thquarter.com
+theblackmarket.com
+tombstone.ws
+troamail.org
+u2tours.com
+vitalogy.org
+whatisthis.com
+wrestlezone.com
+abha.cc
+agadir.cc
+ahsa.ws
+ajman.cc
+ajman.us
+ajman.ws
+albaha.cc
+algerie.cc
+alriyadh.cc
+amman.cc
+aqaba.cc
+arar.ws
+aswan.cc
+baalbeck.cc
+bahraini.cc
+banha.cc
+bizerte.cc
+blida.info
+buraydah.cc
+cameroon.cc
+dhahran.cc
+dhofar.cc
+djibouti.cc
+dominican.cc
+eritrea.cc
+falasteen.cc
+fujairah.cc
+fujairah.us
+fujairah.ws
+gabes.cc
+gafsa.cc
+giza.cc
+guinea.cc
+hamra.cc
+hasakah.com
+hebron.tv
+homs.cc
+ibra.cc
+irbid.ws
+ismailia.cc
+jadida.cc
+jadida.org
+jerash.cc
+jizan.cc
+jouf.cc
+kairouan.cc
+karak.cc
+khaimah.cc
+khartoum.cc
+khobar.cc
+kuwaiti.tv
+kyrgyzstan.cc
+latakia.cc
+lebanese.cc
+lubnan.cc
+lubnan.ws
+madinah.cc
+maghreb.cc
+manama.cc
+mansoura.tv
+marrakesh.cc
+mascara.ws
+meknes.cc
+muscat.tv
+muscat.ws
+nabeul.cc
+nabeul.info
+nablus.cc
+nador.cc
+najaf.cc
+omani.ws
+omdurman.cc
+oran.cc
+oued.info
+oued.org
+oujda.biz
+oujda.cc
+pakistani.ws
+palmyra.cc
+palmyra.ws
+portsaid.cc
+qassem.cc
+quds.cc
+rabat.cc
+rafah.cc
+ramallah.cc
+safat.biz
+safat.info
+safat.us
+safat.ws
+salalah.cc
+salmiya.biz
+sanaa.cc
+seeb.cc
+sfax.ws
+sharm.cc
+sinai.cc
+siria.cc
+sousse.cc
+sudanese.cc
+suez.cc
+tabouk.cc
+tajikistan.cc
+tangiers.cc
+tanta.cc
+tayef.cc
+tetouan.cc
+timor.cc
+tunisian.cc
+urdun.cc
+yanbo.cc
+yemeni.cc
+yunus.cc
+zagazig.cc
+zambia.cc
+5005.lv
+a.org.ua
+bmx.lv
+company.org.ua
+coolmail.ru
+dino.lv
+eclub.lv
+e-mail.am
+fit.lv
+hacker.am
+human.lv
+iphon.biz
+latchess.com
+loveis.lv
+lv-inter.net
+pookmail.com
+sexriga.lv
diff --git a/crates/router/src/utils/user/password.rs b/crates/router/src/utils/user/password.rs
new file mode 100644
index 000000000000..cff17863c32d
--- /dev/null
+++ b/crates/router/src/utils/user/password.rs
@@ -0,0 +1,43 @@
+use argon2::{
+    password_hash::{
+        rand_core::OsRng, Error as argon2Err, PasswordHash, PasswordHasher, PasswordVerifier,
+        SaltString,
+    },
+    Argon2,
+};
+use common_utils::errors::CustomResult;
+use error_stack::{IntoReport, ResultExt};
+use masking::{ExposeInterface, Secret};
+
+use crate::core::errors::UserErrors;
+
+pub fn generate_password_hash(
+    password: Secret<String>,
+) -> CustomResult<Secret<String>, UserErrors> {
+    let salt = SaltString::generate(&mut OsRng);
+
+    let argon2 = Argon2::default();
+    let password_hash = argon2
+        .hash_password(password.expose().as_bytes(), &salt)
+        .into_report()
+        .change_context(UserErrors::InternalServerError)?;
+    Ok(Secret::new(password_hash.to_string()))
+}
+
+pub fn is_correct_password(
+    candidate: Secret<String>,
+    password: Secret<String>,
+) -> CustomResult<bool, UserErrors> {
+    let password = password.expose();
+    let parsed_hash = PasswordHash::new(&password)
+        .into_report()
+        .change_context(UserErrors::InternalServerError)?;
+    let result = Argon2::default().verify_password(candidate.expose().as_bytes(), &parsed_hash);
+    match result {
+        Ok(_) => Ok(true),
+        Err(argon2Err::Password) => Ok(false),
+        Err(e) => Err(e),
+    }
+    .into_report()
+    .change_context(UserErrors::InternalServerError)
+}
diff --git a/crates/router/src/workflows/payment_sync.rs b/crates/router/src/workflows/payment_sync.rs
index 1e77089e0a63..00e7357d896f 100644
--- a/crates/router/src/workflows/payment_sync.rs
+++ b/crates/router/src/workflows/payment_sync.rs
@@ -61,7 +61,13 @@ impl ProcessTrackerWorkflow<AppState> for PaymentsSyncWorkflow {
             .await?;
 
         let (mut payment_data, _, customer, _, _) =
-            payment_flows::payments_operation_core::<api::PSync, _, _, _, Oss>(
+            Box::pin(payment_flows::payments_operation_core::<
+                api::PSync,
+                _,
+                _,
+                _,
+                Oss,
+            >(
                 state,
                 merchant_account.clone(),
                 key_store,
@@ -69,8 +75,9 @@ impl ProcessTrackerWorkflow<AppState> for PaymentsSyncWorkflow {
                 tracking_data.clone(),
                 payment_flows::CallConnectorAction::Trigger,
                 services::AuthFlow::Client,
+                None,
                 api::HeaderPayload::default(),
-            )
+            ))
             .await?;
 
         let terminal_status = [
@@ -149,16 +156,38 @@ impl ProcessTrackerWorkflow<AppState> for PaymentsSyncWorkflow {
                         .await
                         .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
 
+                    let profile_id = payment_data
+                        .payment_intent
+                        .profile_id
+                        .as_ref()
+                        .get_required_value("profile_id")
+                        .change_context(errors::ApiErrorResponse::InternalServerError)
+                        .attach_printable("Could not find profile_id in payment intent")?;
+
+                    let business_profile = db
+                        .find_business_profile_by_profile_id(profile_id)
+                        .await
+                        .to_not_found_response(
+                            errors::ApiErrorResponse::BusinessProfileNotFound {
+                                id: profile_id.to_string(),
+                            },
+                        )?;
+
                     // Trigger the outgoing webhook to notify the merchant about failed payment
                     let operation = operations::PaymentStatus;
-                    utils::trigger_payments_webhook::<_, api_models::payments::PaymentsRequest, _>(
+                    Box::pin(utils::trigger_payments_webhook::<
+                        _,
+                        api_models::payments::PaymentsRequest,
+                        _,
+                    >(
                         merchant_account,
+                        business_profile,
                         payment_data,
                         None,
                         customer,
                         state,
                         operation,
-                    )
+                    ))
                     .await
                     .map_err(|error| logger::warn!(payments_outgoing_webhook_error=?error))
                     .ok();
diff --git a/crates/router/src/workflows/refund_router.rs b/crates/router/src/workflows/refund_router.rs
index 8ca3551cfc0f..934c208f9115 100644
--- a/crates/router/src/workflows/refund_router.rs
+++ b/crates/router/src/workflows/refund_router.rs
@@ -13,7 +13,7 @@ impl ProcessTrackerWorkflow<AppState> for RefundWorkflowRouter {
         state: &'a AppState,
         process: storage::ProcessTracker,
     ) -> Result<(), errors::ProcessTrackerError> {
-        Ok(refund_flow::start_refund_workflow(state, &process).await?)
+        Ok(Box::pin(refund_flow::start_refund_workflow(state, &process)).await?)
     }
 
     async fn error_handler<'a>(
diff --git a/crates/router/tests/cache.rs b/crates/router/tests/cache.rs
index e1fd3a0f0279..4de45c7132a8 100644
--- a/crates/router/tests/cache.rs
+++ b/crates/router/tests/cache.rs
@@ -7,10 +7,14 @@ mod utils;
 #[actix_web::test]
 async fn invalidate_existing_cache_success() {
     // Arrange
-    utils::setup().await;
+    Box::pin(utils::setup()).await;
     let (tx, _) = tokio::sync::oneshot::channel();
-    let state =
-        routes::AppState::new(Settings::default(), tx, Box::new(services::MockApiClient)).await;
+    let state = Box::pin(routes::AppState::new(
+        Settings::default(),
+        tx,
+        Box::new(services::MockApiClient),
+    ))
+    .await;
 
     let cache_key = "cacheKey".to_string();
     let cache_key_value = "val".to_string();
@@ -53,7 +57,7 @@ async fn invalidate_existing_cache_success() {
 #[actix_web::test]
 async fn invalidate_non_existing_cache_success() {
     // Arrange
-    utils::setup().await;
+    Box::pin(utils::setup()).await;
     let cache_key = "cacheKey".to_string();
     let api_key = ("api-key", "test_admin");
     let client = awc::Client::default();
diff --git a/crates/router/tests/connectors/aci.rs b/crates/router/tests/connectors/aci.rs
index 4fe36f36871c..c9ee3a34f2ef 100644
--- a/crates/router/tests/connectors/aci.rs
+++ b/crates/router/tests/connectors/aci.rs
@@ -173,6 +173,7 @@ async fn payments_create_success() {
         connector: Box::new(&CV),
         connector_name: types::Connector::Aci,
         get_token: types::api::GetToken::Connector,
+        merchant_connector_id: None,
     };
     let connector_integration: services::BoxedConnectorIntegration<
         '_,
@@ -214,6 +215,7 @@ async fn payments_create_failure() {
             connector: Box::new(&CV),
             connector_name: types::Connector::Aci,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         };
         let connector_integration: services::BoxedConnectorIntegration<
             '_,
@@ -260,6 +262,7 @@ async fn refund_for_successful_payments() {
         connector: Box::new(&CV),
         connector_name: types::Connector::Aci,
         get_token: types::api::GetToken::Connector,
+        merchant_connector_id: None,
     };
     let tx: oneshot::Sender<()> = oneshot::channel().0;
     let state = routes::AppState::with_storage(
@@ -327,6 +330,7 @@ async fn refunds_create_failure() {
         connector: Box::new(&CV),
         connector_name: types::Connector::Aci,
         get_token: types::api::GetToken::Connector,
+        merchant_connector_id: None,
     };
     let tx: oneshot::Sender<()> = oneshot::channel().0;
     let state = routes::AppState::with_storage(
diff --git a/crates/router/tests/connectors/adyen.rs b/crates/router/tests/connectors/adyen.rs
index 2ee6c4912e7c..4b2cbcb7c4a9 100644
--- a/crates/router/tests/connectors/adyen.rs
+++ b/crates/router/tests/connectors/adyen.rs
@@ -19,9 +19,11 @@ impl utils::Connector for AdyenTest {
             connector: Box::new(&Adyen),
             connector_name: types::Connector::Adyen,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
+    #[cfg(feature = "payouts")]
     fn get_payout_data(&self) -> Option<types::api::PayoutConnectorData> {
         use router::connector::Adyen;
         Some(types::api::PayoutConnectorData {
@@ -67,6 +69,7 @@ impl AdyenTest {
         })
     }
 
+    #[cfg(feature = "payouts")]
     fn get_payout_info(payout_type: enums::PayoutType) -> Option<PaymentInfo> {
         Some(PaymentInfo {
             country: Some(api_models::enums::CountryAlpha2::NL),
diff --git a/crates/router/tests/connectors/airwallex.rs b/crates/router/tests/connectors/airwallex.rs
index 7d9070a94df9..6e7f6c000d28 100644
--- a/crates/router/tests/connectors/airwallex.rs
+++ b/crates/router/tests/connectors/airwallex.rs
@@ -21,6 +21,7 @@ impl Connector for AirwallexTest {
             connector: Box::new(&Airwallex),
             connector_name: types::Connector::Airwallex,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/authorizedotnet.rs b/crates/router/tests/connectors/authorizedotnet.rs
index 4750e122a217..4021d57d543f 100644
--- a/crates/router/tests/connectors/authorizedotnet.rs
+++ b/crates/router/tests/connectors/authorizedotnet.rs
@@ -18,6 +18,7 @@ impl utils::Connector for AuthorizedotnetTest {
             connector: Box::new(&Authorizedotnet),
             connector_name: types::Connector::Authorizedotnet,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/bambora.rs b/crates/router/tests/connectors/bambora.rs
index 5638214202b4..c4da2b900d3e 100644
--- a/crates/router/tests/connectors/bambora.rs
+++ b/crates/router/tests/connectors/bambora.rs
@@ -19,6 +19,7 @@ impl utils::Connector for BamboraTest {
             connector: Box::new(&Bambora),
             connector_name: types::Connector::Bambora,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/bankofamerica.rs b/crates/router/tests/connectors/bankofamerica.rs
new file mode 100644
index 000000000000..766078fa19c0
--- /dev/null
+++ b/crates/router/tests/connectors/bankofamerica.rs
@@ -0,0 +1,421 @@
+use masking::Secret;
+use router::types::{self, api, storage::enums};
+use test_utils::connector_auth;
+
+use crate::utils::{self, ConnectorActions};
+
+#[derive(Clone, Copy)]
+struct BankofamericaTest;
+impl ConnectorActions for BankofamericaTest {}
+impl utils::Connector for BankofamericaTest {
+    fn get_data(&self) -> types::api::ConnectorData {
+        use router::connector::Bankofamerica;
+        types::api::ConnectorData {
+            connector: Box::new(&Bankofamerica),
+            // Remove `dummy_connector` feature gate from module in `main.rs` when updating this to use actual connector variant
+            connector_name: types::Connector::DummyConnector1,
+            get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
+        }
+    }
+
+    fn get_auth_token(&self) -> types::ConnectorAuthType {
+        utils::to_connector_auth_type(
+            connector_auth::ConnectorAuthentication::new()
+                .bankofamerica
+                .expect("Missing connector authentication configuration")
+                .into(),
+        )
+    }
+
+    fn get_name(&self) -> String {
+        "bankofamerica".to_string()
+    }
+}
+
+static CONNECTOR: BankofamericaTest = BankofamericaTest {};
+
+fn get_default_payment_info() -> Option<utils::PaymentInfo> {
+    None
+}
+
+fn payment_method_details() -> Option<types::PaymentsAuthorizeData> {
+    None
+}
+
+// Cards Positive Tests
+// Creates a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_only_authorize_payment() {
+    let response = CONNECTOR
+        .authorize_payment(payment_method_details(), get_default_payment_info())
+        .await
+        .expect("Authorize payment response");
+    assert_eq!(response.status, enums::AttemptStatus::Authorized);
+}
+
+// Captures a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_capture_authorized_payment() {
+    let response = CONNECTOR
+        .authorize_and_capture_payment(payment_method_details(), None, get_default_payment_info())
+        .await
+        .expect("Capture payment response");
+    assert_eq!(response.status, enums::AttemptStatus::Charged);
+}
+
+// Partially captures a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_partially_capture_authorized_payment() {
+    let response = CONNECTOR
+        .authorize_and_capture_payment(
+            payment_method_details(),
+            Some(types::PaymentsCaptureData {
+                amount_to_capture: 50,
+                ..utils::PaymentCaptureType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .expect("Capture payment response");
+    assert_eq!(response.status, enums::AttemptStatus::Charged);
+}
+
+// Synchronizes a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_sync_authorized_payment() {
+    let authorize_response = CONNECTOR
+        .authorize_payment(payment_method_details(), get_default_payment_info())
+        .await
+        .expect("Authorize payment response");
+    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
+    let response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::Authorized,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(
+                    txn_id.unwrap(),
+                ),
+                ..Default::default()
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .expect("PSync response");
+    assert_eq!(response.status, enums::AttemptStatus::Authorized,);
+}
+
+// Voids a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_void_authorized_payment() {
+    let response = CONNECTOR
+        .authorize_and_void_payment(
+            payment_method_details(),
+            Some(types::PaymentsCancelData {
+                connector_transaction_id: String::from(""),
+                cancellation_reason: Some("requested_by_customer".to_string()),
+                ..Default::default()
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .expect("Void payment response");
+    assert_eq!(response.status, enums::AttemptStatus::Voided);
+}
+
+// Refunds a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_refund_manually_captured_payment() {
+    let response = CONNECTOR
+        .capture_payment_and_refund(
+            payment_method_details(),
+            None,
+            None,
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Partially refunds a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_partially_refund_manually_captured_payment() {
+    let response = CONNECTOR
+        .capture_payment_and_refund(
+            payment_method_details(),
+            None,
+            Some(types::RefundsData {
+                refund_amount: 50,
+                ..utils::PaymentRefundType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Synchronizes a refund using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_sync_manually_captured_refund() {
+    let refund_response = CONNECTOR
+        .capture_payment_and_refund(
+            payment_method_details(),
+            None,
+            None,
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    let response = CONNECTOR
+        .rsync_retry_till_status_matches(
+            enums::RefundStatus::Success,
+            refund_response.response.unwrap().connector_refund_id,
+            None,
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Creates a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_make_payment() {
+    let authorize_response = CONNECTOR
+        .make_payment(payment_method_details(), get_default_payment_info())
+        .await
+        .unwrap();
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
+}
+
+// Synchronizes a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_sync_auto_captured_payment() {
+    let authorize_response = CONNECTOR
+        .make_payment(payment_method_details(), get_default_payment_info())
+        .await
+        .unwrap();
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
+    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
+    assert_ne!(txn_id, None, "Empty connector transaction id");
+    let response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::Charged,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(
+                    txn_id.unwrap(),
+                ),
+                capture_method: Some(enums::CaptureMethod::Automatic),
+                ..Default::default()
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(response.status, enums::AttemptStatus::Charged,);
+}
+
+// Refunds a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_refund_auto_captured_payment() {
+    let response = CONNECTOR
+        .make_payment_and_refund(payment_method_details(), None, get_default_payment_info())
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Partially refunds a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_partially_refund_succeeded_payment() {
+    let refund_response = CONNECTOR
+        .make_payment_and_refund(
+            payment_method_details(),
+            Some(types::RefundsData {
+                refund_amount: 50,
+                ..utils::PaymentRefundType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        refund_response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Creates multiple refunds against a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_refund_succeeded_payment_multiple_times() {
+    CONNECTOR
+        .make_payment_and_multiple_refund(
+            payment_method_details(),
+            Some(types::RefundsData {
+                refund_amount: 50,
+                ..utils::PaymentRefundType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await;
+}
+
+// Synchronizes a refund using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_sync_refund() {
+    let refund_response = CONNECTOR
+        .make_payment_and_refund(payment_method_details(), None, get_default_payment_info())
+        .await
+        .unwrap();
+    let response = CONNECTOR
+        .rsync_retry_till_status_matches(
+            enums::RefundStatus::Success,
+            refund_response.response.unwrap().connector_refund_id,
+            None,
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Cards Negative scenerios
+// Creates a payment with incorrect CVC.
+#[actix_web::test]
+async fn should_fail_payment_for_incorrect_cvc() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
+                    card_cvc: Secret::new("12345".to_string()),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Your card's security code is invalid.".to_string(),
+    );
+}
+
+// Creates a payment with incorrect expiry month.
+#[actix_web::test]
+async fn should_fail_payment_for_invalid_exp_month() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
+                    card_exp_month: Secret::new("20".to_string()),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Your card's expiration month is invalid.".to_string(),
+    );
+}
+
+// Creates a payment with incorrect expiry year.
+#[actix_web::test]
+async fn should_fail_payment_for_incorrect_expiry_year() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
+                    card_exp_year: Secret::new("2000".to_string()),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Your card's expiration year is invalid.".to_string(),
+    );
+}
+
+// Voids a payment using automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_fail_void_payment_for_auto_capture() {
+    let authorize_response = CONNECTOR
+        .make_payment(payment_method_details(), get_default_payment_info())
+        .await
+        .unwrap();
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
+    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
+    assert_ne!(txn_id, None, "Empty connector transaction id");
+    let void_response = CONNECTOR
+        .void_payment(txn_id.unwrap(), None, get_default_payment_info())
+        .await
+        .unwrap();
+    assert_eq!(
+        void_response.response.unwrap_err().message,
+        "You cannot cancel this PaymentIntent because it has a status of succeeded."
+    );
+}
+
+// Captures a payment using invalid connector payment id.
+#[actix_web::test]
+async fn should_fail_capture_for_invalid_payment() {
+    let capture_response = CONNECTOR
+        .capture_payment("123456789".to_string(), None, get_default_payment_info())
+        .await
+        .unwrap();
+    assert_eq!(
+        capture_response.response.unwrap_err().message,
+        String::from("No such payment_intent: '123456789'")
+    );
+}
+
+// Refunds a payment with refund amount higher than payment amount.
+#[actix_web::test]
+async fn should_fail_for_refund_amount_higher_than_payment_amount() {
+    let response = CONNECTOR
+        .make_payment_and_refund(
+            payment_method_details(),
+            Some(types::RefundsData {
+                refund_amount: 150,
+                ..utils::PaymentRefundType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Refund amount (₹1.50) is greater than charge amount (₹1.00)",
+    );
+}
+
+// Connector dependent test cases goes here
+
+// [#478]: add unit tests for non 3DS, wallets & webhooks in connector tests
diff --git a/crates/router/tests/connectors/bitpay.rs b/crates/router/tests/connectors/bitpay.rs
index 2f6db7a9e850..755427140c4f 100644
--- a/crates/router/tests/connectors/bitpay.rs
+++ b/crates/router/tests/connectors/bitpay.rs
@@ -17,6 +17,7 @@ impl utils::Connector for BitpayTest {
             connector: Box::new(&Bitpay),
             connector_name: types::Connector::Bitpay,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/bluesnap.rs b/crates/router/tests/connectors/bluesnap.rs
index b54261e77c7e..30052d11da45 100644
--- a/crates/router/tests/connectors/bluesnap.rs
+++ b/crates/router/tests/connectors/bluesnap.rs
@@ -21,6 +21,7 @@ impl utils::Connector for BluesnapTest {
             connector: Box::new(&Bluesnap),
             connector_name: types::Connector::Bluesnap,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/boku.rs b/crates/router/tests/connectors/boku.rs
index e971ad271e49..9c8ac961cacc 100644
--- a/crates/router/tests/connectors/boku.rs
+++ b/crates/router/tests/connectors/boku.rs
@@ -14,6 +14,7 @@ impl utils::Connector for BokuTest {
             connector: Box::new(&Boku),
             connector_name: types::Connector::Boku,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/cashtocode.rs b/crates/router/tests/connectors/cashtocode.rs
index fdb1b94a7149..871677bb692a 100644
--- a/crates/router/tests/connectors/cashtocode.rs
+++ b/crates/router/tests/connectors/cashtocode.rs
@@ -16,6 +16,7 @@ impl utils::Connector for CashtocodeTest {
             connector: Box::new(&Cashtocode),
             connector_name: types::Connector::Cashtocode,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/checkout.rs b/crates/router/tests/connectors/checkout.rs
index 18d6d6d2ddb0..1c369332ef2c 100644
--- a/crates/router/tests/connectors/checkout.rs
+++ b/crates/router/tests/connectors/checkout.rs
@@ -15,6 +15,7 @@ impl utils::Connector for CheckoutTest {
             connector: Box::new(&Checkout),
             connector_name: types::Connector::Checkout,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/coinbase.rs b/crates/router/tests/connectors/coinbase.rs
index cc8cc774a144..512e03a5c94d 100644
--- a/crates/router/tests/connectors/coinbase.rs
+++ b/crates/router/tests/connectors/coinbase.rs
@@ -18,6 +18,7 @@ impl utils::Connector for CoinbaseTest {
             connector: Box::new(&Coinbase),
             connector_name: types::Connector::Coinbase,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/cryptopay.rs b/crates/router/tests/connectors/cryptopay.rs
index 48313e5d1a12..e9c43cee3af6 100644
--- a/crates/router/tests/connectors/cryptopay.rs
+++ b/crates/router/tests/connectors/cryptopay.rs
@@ -17,6 +17,7 @@ impl utils::Connector for CryptopayTest {
             connector: Box::new(&Cryptopay),
             connector_name: types::Connector::Cryptopay,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/cybersource.rs b/crates/router/tests/connectors/cybersource.rs
index 5f9adf39f9b9..70255f68d897 100644
--- a/crates/router/tests/connectors/cybersource.rs
+++ b/crates/router/tests/connectors/cybersource.rs
@@ -20,6 +20,7 @@ impl utils::Connector for Cybersource {
             connector: Box::new(&Cybersource),
             connector_name: types::Connector::Cybersource,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
     fn get_auth_token(&self) -> types::ConnectorAuthType {
diff --git a/crates/router/tests/connectors/dlocal.rs b/crates/router/tests/connectors/dlocal.rs
index 05d42ef7fee9..92ae9da11dc3 100644
--- a/crates/router/tests/connectors/dlocal.rs
+++ b/crates/router/tests/connectors/dlocal.rs
@@ -19,6 +19,7 @@ impl utils::Connector for DlocalTest {
             connector: Box::new(&Dlocal),
             connector_name: types::Connector::Dlocal,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/dummyconnector.rs b/crates/router/tests/connectors/dummyconnector.rs
index 7efaa8329595..75252e85edc2 100644
--- a/crates/router/tests/connectors/dummyconnector.rs
+++ b/crates/router/tests/connectors/dummyconnector.rs
@@ -17,6 +17,7 @@ impl utils::Connector for DummyConnectorTest {
             connector: Box::new(&DummyConnector::<1>),
             connector_name: types::Connector::DummyConnector1,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/fiserv.rs b/crates/router/tests/connectors/fiserv.rs
index 532084a74654..1394667718c5 100644
--- a/crates/router/tests/connectors/fiserv.rs
+++ b/crates/router/tests/connectors/fiserv.rs
@@ -19,6 +19,7 @@ impl utils::Connector for FiservTest {
             connector: Box::new(&Fiserv),
             connector_name: types::Connector::Fiserv,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/forte.rs b/crates/router/tests/connectors/forte.rs
index 703b8900b69b..f0c182d62a49 100644
--- a/crates/router/tests/connectors/forte.rs
+++ b/crates/router/tests/connectors/forte.rs
@@ -19,6 +19,7 @@ impl utils::Connector for ForteTest {
             connector: Box::new(&Forte),
             connector_name: types::Connector::Forte,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/globalpay.rs b/crates/router/tests/connectors/globalpay.rs
index 39e0ed58f4a8..8553f2a768af 100644
--- a/crates/router/tests/connectors/globalpay.rs
+++ b/crates/router/tests/connectors/globalpay.rs
@@ -19,6 +19,7 @@ impl Connector for Globalpay {
             connector: Box::new(&Globalpay),
             connector_name: types::Connector::Globalpay,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/globepay.rs b/crates/router/tests/connectors/globepay.rs
index 607abac73878..fcf61dd6b33d 100644
--- a/crates/router/tests/connectors/globepay.rs
+++ b/crates/router/tests/connectors/globepay.rs
@@ -14,8 +14,9 @@ impl utils::Connector for GlobepayTest {
         use router::connector::Globepay;
         types::api::ConnectorData {
             connector: Box::new(&Globepay),
-            connector_name: types::Connector::DummyConnector1,
+            connector_name: types::Connector::Globepay,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/gocardless.rs b/crates/router/tests/connectors/gocardless.rs
index 50c4bf4afb78..f19e90941b2e 100644
--- a/crates/router/tests/connectors/gocardless.rs
+++ b/crates/router/tests/connectors/gocardless.rs
@@ -12,8 +12,9 @@ impl utils::Connector for GocardlessTest {
         use router::connector::Gocardless;
         types::api::ConnectorData {
             connector: Box::new(&Gocardless),
-            connector_name: types::Connector::DummyConnector1,
+            connector_name: types::Connector::Gocardless,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/helcim.rs b/crates/router/tests/connectors/helcim.rs
index f8eb9635666b..c9a891988f3b 100644
--- a/crates/router/tests/connectors/helcim.rs
+++ b/crates/router/tests/connectors/helcim.rs
@@ -12,8 +12,9 @@ impl utils::Connector for HelcimTest {
         use router::connector::Helcim;
         types::api::ConnectorData {
             connector: Box::new(&Helcim),
-            connector_name: types::Connector::DummyConnector1,
+            connector_name: types::Connector::Helcim,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/iatapay.rs b/crates/router/tests/connectors/iatapay.rs
index c1f4492bcebf..b6469b500c7b 100644
--- a/crates/router/tests/connectors/iatapay.rs
+++ b/crates/router/tests/connectors/iatapay.rs
@@ -18,6 +18,7 @@ impl Connector for IatapayTest {
             connector: Box::new(&Iatapay),
             connector_name: types::Connector::Iatapay,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/main.rs b/crates/router/tests/connectors/main.rs
index ed06312b77ac..fc474818b505 100644
--- a/crates/router/tests/connectors/main.rs
+++ b/crates/router/tests/connectors/main.rs
@@ -11,6 +11,8 @@ mod adyen;
 mod airwallex;
 mod authorizedotnet;
 mod bambora;
+#[cfg(feature = "dummy_connector")]
+mod bankofamerica;
 mod bitpay;
 mod bluesnap;
 mod boku;
@@ -35,13 +37,16 @@ mod nexinets;
 mod nmi;
 mod noon;
 mod nuvei;
+#[cfg(feature = "dummy_connector")]
 mod opayo;
 mod opennode;
+#[cfg(feature = "dummy_connector")]
 mod payeezy;
 mod payme;
 mod paypal;
 mod payu;
 mod powertranz;
+#[cfg(feature = "dummy_connector")]
 mod prophetpay;
 mod rapyd;
 mod shift4;
diff --git a/crates/router/tests/connectors/mollie.rs b/crates/router/tests/connectors/mollie.rs
index e5a1f090d3c8..14c77e2a9f09 100644
--- a/crates/router/tests/connectors/mollie.rs
+++ b/crates/router/tests/connectors/mollie.rs
@@ -15,6 +15,7 @@ impl utils::Connector for MollieTest {
             connector: Box::new(&Mollie),
             connector_name: types::Connector::Mollie,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/multisafepay.rs b/crates/router/tests/connectors/multisafepay.rs
index a5d9dda92211..8502a60b71ce 100644
--- a/crates/router/tests/connectors/multisafepay.rs
+++ b/crates/router/tests/connectors/multisafepay.rs
@@ -17,6 +17,7 @@ impl utils::Connector for MultisafepayTest {
             connector: Box::new(&Multisafepay),
             connector_name: types::Connector::Multisafepay,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/nexinets.rs b/crates/router/tests/connectors/nexinets.rs
index f9b8affb0626..ff4a283e6745 100644
--- a/crates/router/tests/connectors/nexinets.rs
+++ b/crates/router/tests/connectors/nexinets.rs
@@ -20,6 +20,7 @@ impl utils::Connector for NexinetsTest {
             connector: Box::new(&Nexinets),
             connector_name: types::Connector::Nexinets,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/nmi.rs b/crates/router/tests/connectors/nmi.rs
index 42301dc3a24d..24e1d69a6009 100644
--- a/crates/router/tests/connectors/nmi.rs
+++ b/crates/router/tests/connectors/nmi.rs
@@ -16,6 +16,7 @@ impl utils::Connector for NmiTest {
             connector: Box::new(&Nmi),
             connector_name: types::Connector::Nmi,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/noon.rs b/crates/router/tests/connectors/noon.rs
index 01a38fcd7832..0f736e3e528e 100644
--- a/crates/router/tests/connectors/noon.rs
+++ b/crates/router/tests/connectors/noon.rs
@@ -21,6 +21,7 @@ impl utils::Connector for NoonTest {
             connector: Box::new(&Noon),
             connector_name: types::Connector::Noon,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/nuvei.rs b/crates/router/tests/connectors/nuvei.rs
index d0f8fbaa93b0..5d266fb46fe9 100644
--- a/crates/router/tests/connectors/nuvei.rs
+++ b/crates/router/tests/connectors/nuvei.rs
@@ -22,6 +22,7 @@ impl utils::Connector for NuveiTest {
             connector: Box::new(&Nuvei),
             connector_name: types::Connector::Nuvei,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/opayo.rs b/crates/router/tests/connectors/opayo.rs
index 23b1098e2737..97d744d1e9db 100644
--- a/crates/router/tests/connectors/opayo.rs
+++ b/crates/router/tests/connectors/opayo.rs
@@ -16,8 +16,10 @@ impl utils::Connector for OpayoTest {
         use router::connector::Opayo;
         types::api::ConnectorData {
             connector: Box::new(&Opayo),
+            // Remove `dummy_connector` feature gate from module in `main.rs` when updating this to use actual connector variant
             connector_name: types::Connector::DummyConnector1,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/opennode.rs b/crates/router/tests/connectors/opennode.rs
index a46fc20604a5..248bbb02e520 100644
--- a/crates/router/tests/connectors/opennode.rs
+++ b/crates/router/tests/connectors/opennode.rs
@@ -17,6 +17,7 @@ impl utils::Connector for OpennodeTest {
             connector: Box::new(&Opennode),
             connector_name: types::Connector::Opennode,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/payeezy.rs b/crates/router/tests/connectors/payeezy.rs
index 01d8d1ea87ff..1176ad7322bf 100644
--- a/crates/router/tests/connectors/payeezy.rs
+++ b/crates/router/tests/connectors/payeezy.rs
@@ -22,8 +22,10 @@ impl utils::Connector for PayeezyTest {
         use router::connector::Payeezy;
         types::api::ConnectorData {
             connector: Box::new(&Payeezy),
+            // Remove `dummy_connector` feature gate from module in `main.rs` when updating this to use actual connector variant
             connector_name: types::Connector::DummyConnector1,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/payme.rs b/crates/router/tests/connectors/payme.rs
index 68538ad40758..5550ba12af88 100644
--- a/crates/router/tests/connectors/payme.rs
+++ b/crates/router/tests/connectors/payme.rs
@@ -20,6 +20,7 @@ impl utils::Connector for PaymeTest {
             connector: Box::new(&Payme),
             connector_name: types::Connector::Payme,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/paypal.rs b/crates/router/tests/connectors/paypal.rs
index e9df65566930..bfd2620e3f9a 100644
--- a/crates/router/tests/connectors/paypal.rs
+++ b/crates/router/tests/connectors/paypal.rs
@@ -17,6 +17,7 @@ impl Connector for PaypalTest {
             connector: Box::new(&Paypal),
             connector_name: types::Connector::Paypal,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/payu.rs b/crates/router/tests/connectors/payu.rs
index f1030092a4e1..c73205d9fd35 100644
--- a/crates/router/tests/connectors/payu.rs
+++ b/crates/router/tests/connectors/payu.rs
@@ -14,6 +14,7 @@ impl Connector for Payu {
             connector: Box::new(&Payu),
             connector_name: types::Connector::Payu,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/powertranz.rs b/crates/router/tests/connectors/powertranz.rs
index 0f9ce943a40d..eca3f86b5690 100644
--- a/crates/router/tests/connectors/powertranz.rs
+++ b/crates/router/tests/connectors/powertranz.rs
@@ -14,8 +14,9 @@ impl utils::Connector for PowertranzTest {
         use router::connector::Powertranz;
         types::api::ConnectorData {
             connector: Box::new(&Powertranz),
-            connector_name: types::Connector::DummyConnector1,
+            connector_name: types::Connector::Powertranz,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/prophetpay.rs b/crates/router/tests/connectors/prophetpay.rs
index cab2e475ea24..94220c11a6aa 100644
--- a/crates/router/tests/connectors/prophetpay.rs
+++ b/crates/router/tests/connectors/prophetpay.rs
@@ -14,6 +14,7 @@ impl utils::Connector for ProphetpayTest {
             connector: Box::new(&Prophetpay),
             connector_name: types::Connector::Prophetpay,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/rapyd.rs b/crates/router/tests/connectors/rapyd.rs
index 4ca7148a9c61..143f87fc5753 100644
--- a/crates/router/tests/connectors/rapyd.rs
+++ b/crates/router/tests/connectors/rapyd.rs
@@ -19,6 +19,7 @@ impl utils::Connector for Rapyd {
             connector: Box::new(&Rapyd),
             connector_name: types::Connector::Rapyd,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/sample_auth.toml b/crates/router/tests/connectors/sample_auth.toml
index 0966db95a42f..f8f6039d6d36 100644
--- a/crates/router/tests/connectors/sample_auth.toml
+++ b/crates/router/tests/connectors/sample_auth.toml
@@ -183,4 +183,9 @@ api_key="API Key"
 api_key="API Key"
 
 [prophetpay]
-api_key="API Key"
\ No newline at end of file
+api_key="API Key"
+
+[bankofamerica]
+api_key = "MyApiKey"
+key1 = "Merchant id"
+api_secret = "Secret key"
diff --git a/crates/router/tests/connectors/shift4.rs b/crates/router/tests/connectors/shift4.rs
index e236d2ad9d09..fe7a232b3e50 100644
--- a/crates/router/tests/connectors/shift4.rs
+++ b/crates/router/tests/connectors/shift4.rs
@@ -18,6 +18,7 @@ impl utils::Connector for Shift4Test {
             connector: Box::new(&Shift4),
             connector_name: types::Connector::Shift4,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/square.rs b/crates/router/tests/connectors/square.rs
index ba7416c5a158..daed5030ce78 100644
--- a/crates/router/tests/connectors/square.rs
+++ b/crates/router/tests/connectors/square.rs
@@ -20,6 +20,7 @@ impl Connector for SquareTest {
             connector: Box::new(&Square),
             connector_name: types::Connector::Square,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/stax.rs b/crates/router/tests/connectors/stax.rs
index 72c1d89da09a..2acf96507fee 100644
--- a/crates/router/tests/connectors/stax.rs
+++ b/crates/router/tests/connectors/stax.rs
@@ -16,6 +16,7 @@ impl utils::Connector for StaxTest {
             connector: Box::new(&Stax),
             connector_name: types::Connector::Stax,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/stripe.rs b/crates/router/tests/connectors/stripe.rs
index e2ac4a173f54..735dedeffbac 100644
--- a/crates/router/tests/connectors/stripe.rs
+++ b/crates/router/tests/connectors/stripe.rs
@@ -17,6 +17,7 @@ impl utils::Connector for Stripe {
             connector: Box::new(&Stripe),
             connector_name: types::Connector::Stripe,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/trustpay.rs b/crates/router/tests/connectors/trustpay.rs
index cefc0f5ab123..6dcd78f58a7e 100644
--- a/crates/router/tests/connectors/trustpay.rs
+++ b/crates/router/tests/connectors/trustpay.rs
@@ -18,6 +18,7 @@ impl utils::Connector for TrustpayTest {
             connector: Box::new(&Trustpay),
             connector_name: types::Connector::Trustpay,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/tsys.rs b/crates/router/tests/connectors/tsys.rs
index 51d0575a7a57..e7a0d747f441 100644
--- a/crates/router/tests/connectors/tsys.rs
+++ b/crates/router/tests/connectors/tsys.rs
@@ -19,6 +19,7 @@ impl utils::Connector for TsysTest {
             connector: Box::new(&Tsys),
             connector_name: types::Connector::Tsys,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs
index 1cb3b48f72d5..67a0625968fb 100644
--- a/crates/router/tests/connectors/utils.rs
+++ b/crates/router/tests/connectors/utils.rs
@@ -4,9 +4,11 @@ use async_trait::async_trait;
 use common_utils::pii::Email;
 use error_stack::Report;
 use masking::Secret;
+#[cfg(feature = "payouts")]
+use router::core::utils as core_utils;
 use router::{
     configs::settings::Settings,
-    core::{errors, errors::ConnectorError, payments, utils as core_utils},
+    core::{errors, errors::ConnectorError, payments},
     db::StorageImpl,
     routes, services,
     types::{self, api, storage::enums, AccessToken, PaymentAddress, RouterData},
@@ -17,15 +19,21 @@ use wiremock::{Mock, MockServer};
 
 pub trait Connector {
     fn get_data(&self) -> types::api::ConnectorData;
+
     fn get_auth_token(&self) -> types::ConnectorAuthType;
+
     fn get_name(&self) -> String;
+
     fn get_connector_meta(&self) -> Option<serde_json::Value> {
         None
     }
+
     /// interval in seconds to be followed when making the subsequent request whenever needed
     fn get_request_interval(&self) -> u64 {
         5
     }
+
+    #[cfg(feature = "payouts")]
     fn get_payout_data(&self) -> Option<types::api::PayoutConnectorData> {
         None
     }
@@ -72,7 +80,7 @@ pub trait ConnectorActions: Connector {
         )
         .await;
         integration.execute_pretasks(&mut request, &state).await?;
-        call_connector(request, integration).await
+        Box::pin(call_connector(request, integration)).await
     }
 
     async fn create_connector_customer(
@@ -96,7 +104,7 @@ pub trait ConnectorActions: Connector {
         )
         .await;
         integration.execute_pretasks(&mut request, &state).await?;
-        call_connector(request, integration).await
+        Box::pin(call_connector(request, integration)).await
     }
 
     async fn create_connector_pm_token(
@@ -120,7 +128,7 @@ pub trait ConnectorActions: Connector {
         )
         .await;
         integration.execute_pretasks(&mut request, &state).await?;
-        call_connector(request, integration).await
+        Box::pin(call_connector(request, integration)).await
     }
 
     /// For initiating payments when `CaptureMethod` is set to `Automatic`
@@ -148,7 +156,7 @@ pub trait ConnectorActions: Connector {
         )
         .await;
         integration.execute_pretasks(&mut request, &state).await?;
-        call_connector(request, integration).await
+        Box::pin(call_connector(request, integration)).await
     }
 
     async fn sync_payment(
@@ -161,7 +169,7 @@ pub trait ConnectorActions: Connector {
             payment_data.unwrap_or_else(|| PaymentSyncType::default().0),
             payment_info,
         );
-        call_connector(request, integration).await
+        Box::pin(call_connector(request, integration)).await
     }
 
     /// will retry the psync till the given status matches or retry max 3 times
@@ -199,7 +207,7 @@ pub trait ConnectorActions: Connector {
             },
             payment_info,
         );
-        call_connector(request, integration).await
+        Box::pin(call_connector(request, integration)).await
     }
 
     async fn authorize_and_capture_payment(
@@ -235,7 +243,7 @@ pub trait ConnectorActions: Connector {
             },
             payment_info,
         );
-        call_connector(request, integration).await
+        Box::pin(call_connector(request, integration)).await
     }
 
     async fn authorize_and_void_payment(
@@ -272,7 +280,7 @@ pub trait ConnectorActions: Connector {
             },
             payment_info,
         );
-        call_connector(request, integration).await
+        Box::pin(call_connector(request, integration)).await
     }
 
     async fn capture_payment_and_refund(
@@ -392,7 +400,7 @@ pub trait ConnectorActions: Connector {
             }),
             payment_info,
         );
-        call_connector(request, integration).await
+        Box::pin(call_connector(request, integration)).await
     }
 
     /// will retry the rsync till the given status matches or retry max 3 times
@@ -423,6 +431,7 @@ pub trait ConnectorActions: Connector {
         Err(errors::ConnectorError::ProcessingStepFailed(None).into())
     }
 
+    #[cfg(feature = "payouts")]
     fn get_payout_request<Flow, Res>(
         &self,
         connector_payout_id: Option<String>,
@@ -534,6 +543,7 @@ pub trait ConnectorActions: Connector {
         }
     }
 
+    #[cfg(feature = "payouts")]
     async fn verify_payout_eligibility(
         &self,
         payout_type: enums::PayoutType,
@@ -572,6 +582,7 @@ pub trait ConnectorActions: Connector {
         Ok(res.response.unwrap())
     }
 
+    #[cfg(feature = "payouts")]
     async fn fulfill_payout(
         &self,
         connector_payout_id: Option<String>,
@@ -611,6 +622,7 @@ pub trait ConnectorActions: Connector {
         Ok(res.response.unwrap())
     }
 
+    #[cfg(feature = "payouts")]
     async fn create_payout(
         &self,
         connector_customer: Option<String>,
@@ -651,6 +663,7 @@ pub trait ConnectorActions: Connector {
         Ok(res.response.unwrap())
     }
 
+    #[cfg(feature = "payouts")]
     async fn cancel_payout(
         &self,
         connector_payout_id: String,
@@ -691,6 +704,7 @@ pub trait ConnectorActions: Connector {
         Ok(res.response.unwrap())
     }
 
+    #[cfg(feature = "payouts")]
     async fn create_and_fulfill_payout(
         &self,
         connector_customer: Option<String>,
@@ -714,6 +728,7 @@ pub trait ConnectorActions: Connector {
         Ok(fulfill_res)
     }
 
+    #[cfg(feature = "payouts")]
     async fn create_and_cancel_payout(
         &self,
         connector_customer: Option<String>,
@@ -737,6 +752,7 @@ pub trait ConnectorActions: Connector {
         Ok(cancel_res)
     }
 
+    #[cfg(feature = "payouts")]
     async fn create_payout_recipient(
         &self,
         payout_type: enums::PayoutType,
diff --git a/crates/router/tests/connectors/volt.rs b/crates/router/tests/connectors/volt.rs
index 8435e39c6569..0df21640c777 100644
--- a/crates/router/tests/connectors/volt.rs
+++ b/crates/router/tests/connectors/volt.rs
@@ -12,8 +12,9 @@ impl utils::Connector for VoltTest {
         use router::connector::Volt;
         types::api::ConnectorData {
             connector: Box::new(&Volt),
-            connector_name: types::Connector::DummyConnector1,
+            connector_name: types::Connector::Volt,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/wise.rs b/crates/router/tests/connectors/wise.rs
index fad3a73cafed..fb65397e1a22 100644
--- a/crates/router/tests/connectors/wise.rs
+++ b/crates/router/tests/connectors/wise.rs
@@ -1,10 +1,16 @@
+#[cfg(feature = "payouts")]
 use api_models::payments::{Address, AddressDetails};
+#[cfg(feature = "payouts")]
 use masking::Secret;
-use router::types::{self, api, storage::enums, PaymentAddress};
+use router::types;
+#[cfg(feature = "payouts")]
+use router::types::{api, storage::enums, PaymentAddress};
 
+#[cfg(feature = "payouts")]
+use crate::utils::PaymentInfo;
 use crate::{
     connector_auth,
-    utils::{self, ConnectorActions, PaymentInfo},
+    utils::{self, ConnectorActions},
 };
 
 struct WiseTest;
@@ -16,9 +22,11 @@ impl utils::Connector for WiseTest {
             connector: Box::new(&Adyen),
             connector_name: types::Connector::Adyen,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
+    #[cfg(feature = "payouts")]
     fn get_payout_data(&self) -> Option<types::api::PayoutConnectorData> {
         use router::connector::Wise;
         Some(types::api::PayoutConnectorData {
@@ -43,6 +51,7 @@ impl utils::Connector for WiseTest {
 }
 
 impl WiseTest {
+    #[cfg(feature = "payouts")]
     fn get_payout_info() -> Option<PaymentInfo> {
         Some(PaymentInfo {
             country: Some(api_models::enums::CountryAlpha2::NL),
@@ -74,6 +83,7 @@ impl WiseTest {
     }
 }
 
+#[cfg(feature = "payouts")]
 static CONNECTOR: WiseTest = WiseTest {};
 
 /******************** Payouts test cases ********************/
diff --git a/crates/router/tests/connectors/worldline.rs b/crates/router/tests/connectors/worldline.rs
index b9ea1364fdb1..6163949c6c58 100644
--- a/crates/router/tests/connectors/worldline.rs
+++ b/crates/router/tests/connectors/worldline.rs
@@ -22,6 +22,7 @@ impl utils::Connector for WorldlineTest {
             connector: Box::new(&Worldline),
             connector_name: types::Connector::Worldline,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/worldpay.rs b/crates/router/tests/connectors/worldpay.rs
index a7e0f19af71b..bf598e0b37b1 100644
--- a/crates/router/tests/connectors/worldpay.rs
+++ b/crates/router/tests/connectors/worldpay.rs
@@ -23,6 +23,7 @@ impl utils::Connector for Worldpay {
             connector: Box::new(&Worldpay),
             connector_name: types::Connector::Worldpay,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/connectors/zen.rs b/crates/router/tests/connectors/zen.rs
index 3076c4be6a42..12f914e13c1a 100644
--- a/crates/router/tests/connectors/zen.rs
+++ b/crates/router/tests/connectors/zen.rs
@@ -21,6 +21,7 @@ impl utils::Connector for ZenTest {
             connector: Box::new(&Zen),
             connector_name: types::Connector::Zen,
             get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
         }
     }
 
diff --git a/crates/router/tests/customers.rs b/crates/router/tests/customers.rs
index aa17635388fd..065f98fe6609 100644
--- a/crates/router/tests/customers.rs
+++ b/crates/router/tests/customers.rs
@@ -10,7 +10,7 @@ mod utils;
 #[ignore]
 // verify the API-KEY/merchant id has stripe as first choice
 async fn customer_success() {
-    utils::setup().await;
+    Box::pin(utils::setup()).await;
 
     let customer_id = format!("customer_{}", uuid::Uuid::new_v4());
     let api_key = ("API-KEY", "MySecretApiKey");
@@ -79,7 +79,7 @@ async fn customer_success() {
 #[ignore]
 // verify the API-KEY/merchant id has stripe as first choice
 async fn customer_failure() {
-    utils::setup().await;
+    Box::pin(utils::setup()).await;
 
     let customer_id = format!("customer_{}", uuid::Uuid::new_v4());
     let api_key = ("api-key", "MySecretApiKey");
diff --git a/crates/router/tests/integration_demo.rs b/crates/router/tests/integration_demo.rs
index 16e7ead0a383..5bdf9a5f525e 100644
--- a/crates/router/tests/integration_demo.rs
+++ b/crates/router/tests/integration_demo.rs
@@ -10,7 +10,7 @@ use utils::{mk_service, ApiKey, AppClient, MerchantId, PaymentId, Status};
 /// 1) Create Merchant account
 #[actix_web::test]
 async fn create_merchant_account() {
-    let server = mk_service().await;
+    let server = Box::pin(mk_service()).await;
     let client = AppClient::guest();
     let admin_client = client.admin("test_admin");
 
@@ -59,7 +59,7 @@ async fn create_merchant_account() {
 #[actix_web::test]
 async fn partial_refund() {
     let authentication = ConnectorAuthentication::new();
-    let server = mk_service().await;
+    let server = Box::pin(mk_service()).await;
 
     let client = AppClient::guest();
     let admin_client = client.admin("test_admin");
@@ -125,7 +125,7 @@ async fn partial_refund() {
 #[actix_web::test]
 async fn exceed_refund() {
     let authentication = ConnectorAuthentication::new();
-    let server = mk_service().await;
+    let server = Box::pin(mk_service()).await;
 
     let client = AppClient::guest();
     let admin_client = client.admin("test_admin");
diff --git a/crates/router/tests/payments.rs b/crates/router/tests/payments.rs
index 551960ac1380..9d48aaddd451 100644
--- a/crates/router/tests/payments.rs
+++ b/crates/router/tests/payments.rs
@@ -24,7 +24,7 @@ use uuid::Uuid;
 #[ignore]
 // verify the API-KEY/merchant id has stripe as first choice
 async fn payments_create_stripe() {
-    utils::setup().await;
+    Box::pin(utils::setup()).await;
 
     let payment_id = format!("test_{}", uuid::Uuid::new_v4());
     let api_key = ("API-KEY", "MySecretApiKey");
@@ -93,7 +93,7 @@ async fn payments_create_stripe() {
 #[ignore]
 // verify the API-KEY/merchant id has adyen as first choice
 async fn payments_create_adyen() {
-    utils::setup().await;
+    Box::pin(utils::setup()).await;
 
     let payment_id = format!("test_{}", uuid::Uuid::new_v4());
     let api_key = ("API-KEY", "321");
@@ -162,7 +162,7 @@ async fn payments_create_adyen() {
 // verify the API-KEY/merchant id has stripe as first choice
 #[ignore]
 async fn payments_create_fail() {
-    utils::setup().await;
+    Box::pin(utils::setup()).await;
 
     let payment_id = format!("test_{}", uuid::Uuid::new_v4());
     let api_key = ("API-KEY", "MySecretApiKey");
@@ -221,7 +221,7 @@ async fn payments_create_fail() {
 #[actix_web::test]
 #[ignore]
 async fn payments_todo() {
-    utils::setup().await;
+    Box::pin(utils::setup()).await;
 
     let client = awc::Client::default();
     let mut response;
@@ -360,19 +360,26 @@ async fn payments_create_core() {
     };
     let expected_response =
         services::ApplicationResponse::JsonWithHeaders((expected_response, vec![]));
-    let actual_response =
-        payments::payments_core::<api::Authorize, api::PaymentsResponse, _, _, _, Oss>(
-            state,
-            merchant_account,
-            key_store,
-            payments::PaymentCreate,
-            req,
-            services::AuthFlow::Merchant,
-            payments::CallConnectorAction::Trigger,
-            api::HeaderPayload::default(),
-        )
-        .await
-        .unwrap();
+    let actual_response = Box::pin(payments::payments_core::<
+        api::Authorize,
+        api::PaymentsResponse,
+        _,
+        _,
+        _,
+        Oss,
+    >(
+        state,
+        merchant_account,
+        key_store,
+        payments::PaymentCreate,
+        req,
+        services::AuthFlow::Merchant,
+        payments::CallConnectorAction::Trigger,
+        None,
+        api::HeaderPayload::default(),
+    ))
+    .await
+    .unwrap();
     assert_eq!(expected_response, actual_response);
 }
 
@@ -530,18 +537,25 @@ async fn payments_create_core_adyen_no_redirect() {
         },
         vec![],
     ));
-    let actual_response =
-        payments::payments_core::<api::Authorize, api::PaymentsResponse, _, _, _, Oss>(
-            state,
-            merchant_account,
-            key_store,
-            payments::PaymentCreate,
-            req,
-            services::AuthFlow::Merchant,
-            payments::CallConnectorAction::Trigger,
-            api::HeaderPayload::default(),
-        )
-        .await
-        .unwrap();
+    let actual_response = Box::pin(payments::payments_core::<
+        api::Authorize,
+        api::PaymentsResponse,
+        _,
+        _,
+        _,
+        Oss,
+    >(
+        state,
+        merchant_account,
+        key_store,
+        payments::PaymentCreate,
+        req,
+        services::AuthFlow::Merchant,
+        payments::CallConnectorAction::Trigger,
+        None,
+        api::HeaderPayload::default(),
+    ))
+    .await
+    .unwrap();
     assert_eq!(expected_response, actual_response);
 }
diff --git a/crates/router/tests/payments2.rs b/crates/router/tests/payments2.rs
index 96ed131dc6f8..5d4ca844061f 100644
--- a/crates/router/tests/payments2.rs
+++ b/crates/router/tests/payments2.rs
@@ -120,7 +120,7 @@ async fn payments_create_core() {
     };
     let expected_response =
         services::ApplicationResponse::JsonWithHeaders((expected_response, vec![]));
-    let actual_response = router::core::payments::payments_core::<
+    let actual_response = Box::pin(router::core::payments::payments_core::<
         api::Authorize,
         api::PaymentsResponse,
         _,
@@ -135,8 +135,9 @@ async fn payments_create_core() {
         req,
         services::AuthFlow::Merchant,
         payments::CallConnectorAction::Trigger,
+        None,
         api::HeaderPayload::default(),
-    )
+    ))
     .await
     .unwrap();
     assert_eq!(expected_response, actual_response);
@@ -298,7 +299,7 @@ async fn payments_create_core_adyen_no_redirect() {
         },
         vec![],
     ));
-    let actual_response = router::core::payments::payments_core::<
+    let actual_response = Box::pin(router::core::payments::payments_core::<
         api::Authorize,
         api::PaymentsResponse,
         _,
@@ -313,8 +314,9 @@ async fn payments_create_core_adyen_no_redirect() {
         req,
         services::AuthFlow::Merchant,
         payments::CallConnectorAction::Trigger,
+        None,
         api::HeaderPayload::default(),
-    )
+    ))
     .await
     .unwrap();
     assert_eq!(expected_response, actual_response);
diff --git a/crates/router/tests/payouts.rs b/crates/router/tests/payouts.rs
index 566930cd4e31..ab0bc891a7cc 100644
--- a/crates/router/tests/payouts.rs
+++ b/crates/router/tests/payouts.rs
@@ -4,7 +4,7 @@ mod utils;
 
 #[actix_web::test]
 async fn payouts_todo() {
-    utils::setup().await;
+    Box::pin(utils::setup()).await;
 
     let client = awc::Client::default();
     let mut response;
diff --git a/crates/router/tests/refunds.rs b/crates/router/tests/refunds.rs
index c9e08d223503..6b9dfd5ed4a2 100644
--- a/crates/router/tests/refunds.rs
+++ b/crates/router/tests/refunds.rs
@@ -11,7 +11,7 @@ mod utils;
 #[actix_web::test]
 // verify the API-KEY/merchant id has stripe as first choice
 async fn refund_create_fail_stripe() {
-    let app = mk_service().await;
+    let app = Box::pin(mk_service()).await;
     let client = AppClient::guest();
 
     let user_client = client.user("321");
@@ -25,7 +25,7 @@ async fn refund_create_fail_stripe() {
 #[actix_web::test]
 // verify the API-KEY/merchant id has adyen as first choice
 async fn refund_create_fail_adyen() {
-    let app = mk_service().await;
+    let app = Box::pin(mk_service()).await;
     let client = AppClient::guest();
 
     let user_client = client.user("321");
@@ -39,7 +39,7 @@ async fn refund_create_fail_adyen() {
 #[actix_web::test]
 #[ignore]
 async fn refunds_todo() {
-    utils::setup().await;
+    Box::pin(utils::setup()).await;
 
     let client = awc::Client::default();
     let mut response;
diff --git a/crates/router/tests/services.rs b/crates/router/tests/services.rs
index 64f1c3d8ee1b..eff7fe7f8738 100644
--- a/crates/router/tests/services.rs
+++ b/crates/router/tests/services.rs
@@ -10,8 +10,12 @@ async fn get_redis_conn_failure() {
     // Arrange
     utils::setup().await;
     let (tx, _) = tokio::sync::oneshot::channel();
-    let state =
-        routes::AppState::new(Settings::default(), tx, Box::new(services::MockApiClient)).await;
+    let state = Box::pin(routes::AppState::new(
+        Settings::default(),
+        tx,
+        Box::new(services::MockApiClient),
+    ))
+    .await;
 
     let _ = state.store.get_redis_conn().map(|conn| {
         conn.is_redis_available
@@ -28,10 +32,14 @@ async fn get_redis_conn_failure() {
 #[tokio::test]
 async fn get_redis_conn_success() {
     // Arrange
-    utils::setup().await;
+    Box::pin(utils::setup()).await;
     let (tx, _) = tokio::sync::oneshot::channel();
-    let state =
-        routes::AppState::new(Settings::default(), tx, Box::new(services::MockApiClient)).await;
+    let state = Box::pin(routes::AppState::new(
+        Settings::default(),
+        tx,
+        Box::new(services::MockApiClient),
+    ))
+    .await;
 
     // Act
     let result = state.store.get_redis_conn();
diff --git a/crates/router/tests/utils.rs b/crates/router/tests/utils.rs
index 274c011df7a0..6cddbc043662 100644
--- a/crates/router/tests/utils.rs
+++ b/crates/router/tests/utils.rs
@@ -20,7 +20,7 @@ static SERVER: OnceCell<bool> = OnceCell::const_new();
 
 async fn spawn_server() -> bool {
     let conf = Settings::new().expect("invalid settings");
-    let server = router::start_server(conf)
+    let server = Box::pin(router::start_server(conf))
         .await
         .expect("failed to create server");
 
@@ -29,7 +29,7 @@ async fn spawn_server() -> bool {
 }
 
 pub async fn setup() {
-    SERVER.get_or_init(spawn_server).await;
+    Box::pin(SERVER.get_or_init(spawn_server)).await;
 }
 
 const STRIPE_MOCK: &str = "http://localhost:12111/";
diff --git a/crates/router_env/Cargo.toml b/crates/router_env/Cargo.toml
index 1181685d723b..266baf0e3863 100644
--- a/crates/router_env/Cargo.toml
+++ b/crates/router_env/Cargo.toml
@@ -23,7 +23,7 @@ strum = { version = "0.24.1", features = ["derive"] }
 time = { version = "0.3.21", default-features = false, features = ["formatting"] }
 tokio = { version = "1.28.2" }
 tracing = { version = "=0.1.36" }
-tracing-actix-web = { version = "0.7.5", features = ["opentelemetry_0_19"], optional = true }
+tracing-actix-web = { version = "0.7.8", features = ["opentelemetry_0_19", "uuid_v7"], optional = true }
 tracing-appender = { version = "0.2.2" }
 tracing-attributes = "=0.1.22"
 tracing-opentelemetry = { version = "0.19.0" }
diff --git a/crates/router_env/src/lib.rs b/crates/router_env/src/lib.rs
index d3612767ff9d..e75606aa1531 100644
--- a/crates/router_env/src/lib.rs
+++ b/crates/router_env/src/lib.rs
@@ -1,5 +1,5 @@
 #![forbid(unsafe_code)]
-#![warn(missing_docs, missing_debug_implementations)]
+#![warn(missing_debug_implementations)]
 
 //!
 //! Environment of payment router: logger, basic config, its environment awareness.
@@ -22,6 +22,7 @@ pub mod vergen;
 pub use logger::*;
 pub use once_cell;
 pub use opentelemetry;
+use strum::Display;
 pub use tracing;
 #[cfg(feature = "actix_web")]
 pub use tracing_actix_web;
@@ -29,3 +30,19 @@ pub use tracing_appender;
 
 #[doc(inline)]
 pub use self::env::*;
+use crate::types::FlowMetric;
+
+/// Analytics Flow routes Enums
+/// Info - Dimensions and filters available for the domain
+/// Filters - Set of values present for the dimension
+/// Metrics - Analytical data on dimensions and metrics
+#[derive(Debug, Display, Clone, PartialEq, Eq)]
+pub enum AnalyticsFlow {
+    GetInfo,
+    GetPaymentFilters,
+    GetRefundFilters,
+    GetRefundsMetrics,
+    GetPaymentMetrics,
+}
+
+impl FlowMetric for AnalyticsFlow {}
diff --git a/crates/router_env/src/logger/formatter.rs b/crates/router_env/src/logger/formatter.rs
index ce2fd74e0e87..4fd94c221637 100644
--- a/crates/router_env/src/logger/formatter.rs
+++ b/crates/router_env/src/logger/formatter.rs
@@ -51,6 +51,8 @@ const REQUEST_METHOD: &str = "request_method";
 const REQUEST_URL_PATH: &str = "request_url_path";
 const REQUEST_ID: &str = "request_id";
 const WORKFLOW_ID: &str = "workflow_id";
+const GLOBAL_ID: &str = "global_id";
+const SESSION_ID: &str = "session_id";
 
 /// Set of predefined implicit keys.
 pub static IMPLICIT_KEYS: Lazy<rustc_hash::FxHashSet<&str>> = Lazy::new(|| {
@@ -85,6 +87,8 @@ pub static EXTRA_IMPLICIT_KEYS: Lazy<rustc_hash::FxHashSet<&str>> = Lazy::new(||
     set.insert(REQUEST_METHOD);
     set.insert(REQUEST_URL_PATH);
     set.insert(REQUEST_ID);
+    set.insert(GLOBAL_ID);
+    set.insert(SESSION_ID);
     set.insert(WORKFLOW_ID);
 
     set
diff --git a/crates/router_env/src/logger/types.rs b/crates/router_env/src/logger/types.rs
index d63ddce58f30..9cd678083959 100644
--- a/crates/router_env/src/logger/types.rs
+++ b/crates/router_env/src/logger/types.rs
@@ -163,6 +163,26 @@ pub enum Flow {
     RefundsUpdate,
     /// Refunds list flow.
     RefundsList,
+    /// Routing create flow,
+    RoutingCreateConfig,
+    /// Routing link config
+    RoutingLinkConfig,
+    /// Routing link config
+    RoutingUnlinkConfig,
+    /// Routing retrieve config
+    RoutingRetrieveConfig,
+    /// Routing retrieve active config
+    RoutingRetrieveActiveConfig,
+    /// Routing retrieve default config
+    RoutingRetrieveDefaultConfig,
+    /// Routing retrieve dictionary
+    RoutingRetrieveDictionary,
+    /// Routing update config
+    RoutingUpdateConfig,
+    /// Routing update default config
+    RoutingUpdateDefaultConfig,
+    /// Routing delete config
+    RoutingDeleteConfig,
     /// Incoming Webhook Receive
     IncomingWebhookReceive,
     /// Validate payment method flow
@@ -215,6 +235,16 @@ pub enum Flow {
     BusinessProfileList,
     /// Different verification flows
     Verification,
+    /// Gsm Rule Creation flow
+    GsmRuleCreate,
+    /// Gsm Rule Retrieve flow
+    GsmRuleRetrieve,
+    /// Gsm Rule Update flow
+    GsmRuleUpdate,
+    /// Gsm Rule Delete flow
+    GsmRuleDelete,
+    /// User connect account
+    UserConnectAccount,
 }
 
 ///
diff --git a/crates/router_env/src/metrics.rs b/crates/router_env/src/metrics.rs
index e4943699ee5b..14402a7a6e91 100644
--- a/crates/router_env/src/metrics.rs
+++ b/crates/router_env/src/metrics.rs
@@ -63,3 +63,22 @@ macro_rules! histogram_metric {
         > = once_cell::sync::Lazy::new(|| $meter.f64_histogram($description).init());
     };
 }
+
+/// Create a [`Histogram`][Histogram] u64 metric with the specified name and an optional description,
+/// associated with the specified meter. Note that the meter must be to a valid [`Meter`][Meter].
+///
+/// [Histogram]: opentelemetry::metrics::Histogram
+/// [Meter]: opentelemetry::metrics::Meter
+#[macro_export]
+macro_rules! histogram_metric_u64 {
+    ($name:ident, $meter:ident) => {
+        pub(crate) static $name: once_cell::sync::Lazy<
+            $crate::opentelemetry::metrics::Histogram<u64>,
+        > = once_cell::sync::Lazy::new(|| $meter.u64_histogram(stringify!($name)).init());
+    };
+    ($name:ident, $meter:ident, $description:literal) => {
+        pub(crate) static $name: once_cell::sync::Lazy<
+            $crate::opentelemetry::metrics::Histogram<u64>,
+        > = once_cell::sync::Lazy::new(|| $meter.u64_histogram($description).init());
+    };
+}
diff --git a/crates/scheduler/Cargo.toml b/crates/scheduler/Cargo.toml
index 7ce61d9f59f4..e0b68c709e8d 100644
--- a/crates/scheduler/Cargo.toml
+++ b/crates/scheduler/Cargo.toml
@@ -32,9 +32,6 @@ redis_interface = { version = "0.1.0", path = "../redis_interface" }
 router_env = { version = "0.1.0", path = "../router_env", features = ["log_extra_implicit_fields", "log_custom_entries_to_extra"] }
 storage_impl = { version = "0.1.0", path = "../storage_impl", default-features = false }
 
-[target.'cfg(not(target_os = "windows"))'.dependencies]
-signal-hook-tokio = { version = "0.3.1", features = ["futures-v0_3"] }
-
 # [[bin]]
 # name = "scheduler"
 # path = "src/bin/scheduler.rs"
diff --git a/crates/storage_impl/Cargo.toml b/crates/storage_impl/Cargo.toml
index 8fb59d213364..77589cc7d782 100644
--- a/crates/storage_impl/Cargo.toml
+++ b/crates/storage_impl/Cargo.toml
@@ -9,41 +9,39 @@ license.workspace = true
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 [features]
-kms = ["external_services/kms"]
 default = ["olap", "oltp"]
-oltp = ["data_models/oltp"]
+oltp = []
 olap = ["data_models/olap"]
 
 [dependencies]
 # First Party dependencies
-common_utils = { version = "0.1.0", path = "../common_utils" }
 api_models = { version = "0.1.0", path = "../api_models" }
-diesel_models = { version = "0.1.0", path = "../diesel_models" }
+common_utils = { version = "0.1.0", path = "../common_utils" }
 data_models = { version = "0.1.0", path = "../data_models", default-features = false }
+diesel_models = { version = "0.1.0", path = "../diesel_models" }
 masking = { version = "0.1.0", path = "../masking" }
 redis_interface = { version = "0.1.0", path = "../redis_interface" }
-router_env = { version = "0.1.0", path = "../router_env" }
-external_services = { version = "0.1.0", path = "../external_services" }
 router_derive = { version = "0.1.0", path = "../router_derive" }
+router_env = { version = "0.1.0", path = "../router_env" }
 
 # Third party crates
 actix-web = "4.3.1"
-async-bb8-diesel = "0.1.0"
+async-bb8-diesel = { git = "https://github.com/jarnura/async-bb8-diesel", rev = "53b4ab901aab7635c8215fd1c2d542c8db443094" }
 async-trait = "0.1.72"
 bb8 = "0.8.1"
 bytes = "1.4.0"
 config = { version = "0.13.3", features = ["toml"] }
 crc32fast = "1.3.2"
-futures = "0.3.28"
 diesel = { version = "2.1.0", default-features = false, features = ["postgres"] }
 dyn-clone = "1.0.12"
 error-stack = "0.3.1"
+futures = "0.3.28"
 http = "0.2.9"
 mime = "0.3.17"
 moka = { version = "0.11.3", features = ["future"] }
 once_cell = "1.18.0"
 ring = "0.16.20"
-thiserror = "1.0.40"
-tokio = { version = "1.28.2", features = ["rt-multi-thread"] }
 serde = { version = "1.0.185", features = ["derive"] }
 serde_json = "1.0.105"
+thiserror = "1.0.40"
+tokio = { version = "1.28.2", features = ["rt-multi-thread"] }
diff --git a/crates/storage_impl/src/connector_response.rs b/crates/storage_impl/src/connector_response.rs
deleted file mode 100644
index 7d4ff6df94d9..000000000000
--- a/crates/storage_impl/src/connector_response.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-use diesel_models::connector_response::ConnectorResponse;
-
-use crate::redis::kv_store::KvStorePartition;
-
-impl KvStorePartition for ConnectorResponse {}
diff --git a/crates/storage_impl/src/consts.rs b/crates/storage_impl/src/consts.rs
deleted file mode 100644
index 04eab6176f94..000000000000
--- a/crates/storage_impl/src/consts.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-// TTL for KV setup
-pub(crate) const KV_TTL: u32 = 300;
diff --git a/crates/storage_impl/src/lib.rs b/crates/storage_impl/src/lib.rs
index dd8d71fc701e..dc0dea4bb59c 100644
--- a/crates/storage_impl/src/lib.rs
+++ b/crates/storage_impl/src/lib.rs
@@ -1,15 +1,13 @@
 use std::sync::Arc;
 
 use data_models::errors::{StorageError, StorageResult};
-use diesel_models::{self as store};
+use diesel_models as store;
 use error_stack::ResultExt;
 use masking::StrongSecret;
 use redis::{kv_store::RedisConnInterface, RedisStore};
 mod address;
 pub mod config;
 pub mod connection;
-mod connector_response;
-mod consts;
 pub mod database;
 pub mod errors;
 mod lookup;
@@ -32,6 +30,7 @@ pub struct RouterStore<T: DatabaseStore> {
     db_store: T,
     cache_store: RedisStore,
     master_encryption_key: StrongSecret<Vec<u8>>,
+    pub request_id: Option<String>,
 }
 
 #[async_trait::async_trait]
@@ -104,6 +103,7 @@ impl<T: DatabaseStore> RouterStore<T> {
             db_store,
             cache_store,
             master_encryption_key: encryption_key,
+            request_id: None,
         })
     }
 
@@ -129,6 +129,7 @@ impl<T: DatabaseStore> RouterStore<T> {
             db_store,
             cache_store,
             master_encryption_key: encryption_key,
+            request_id: None,
         })
     }
 }
@@ -138,6 +139,8 @@ pub struct KVRouterStore<T: DatabaseStore> {
     router_store: RouterStore<T>,
     drainer_stream_name: String,
     drainer_num_partitions: u8,
+    ttl_for_kv: u32,
+    pub request_id: Option<String>,
 }
 
 #[async_trait::async_trait]
@@ -146,13 +149,14 @@ where
     RouterStore<T>: DatabaseStore,
     T: DatabaseStore,
 {
-    type Config = (RouterStore<T>, String, u8);
+    type Config = (RouterStore<T>, String, u8, u32);
     async fn new(config: Self::Config, _test_transaction: bool) -> StorageResult<Self> {
-        let (router_store, drainer_stream_name, drainer_num_partitions) = config;
+        let (router_store, drainer_stream_name, drainer_num_partitions, ttl_for_kv) = config;
         Ok(Self::from_store(
             router_store,
             drainer_stream_name,
             drainer_num_partitions,
+            ttl_for_kv,
         ))
     }
     fn get_master_pool(&self) -> &PgPool {
@@ -176,11 +180,16 @@ impl<T: DatabaseStore> KVRouterStore<T> {
         store: RouterStore<T>,
         drainer_stream_name: String,
         drainer_num_partitions: u8,
+        ttl_for_kv: u32,
     ) -> Self {
+        let request_id = store.request_id.clone();
+
         Self {
             router_store: store,
             drainer_stream_name,
             drainer_num_partitions,
+            ttl_for_kv,
+            request_id,
         }
     }
 
@@ -200,6 +209,9 @@ impl<T: DatabaseStore> KVRouterStore<T> {
     where
         R: crate::redis::kv_store::KvStorePartition,
     {
+        let global_id = format!("{}", partition_key);
+        let request_id = self.request_id.clone().unwrap_or_default();
+
         let shard_key = R::shard_key(partition_key, self.drainer_num_partitions);
         let stream_name = self.get_drainer_stream_name(&shard_key);
         self.router_store
@@ -209,7 +221,7 @@ impl<T: DatabaseStore> KVRouterStore<T> {
                 &stream_name,
                 &redis_interface::RedisEntryId::AutoGeneratedID,
                 redis_entry
-                    .to_field_value_pairs()
+                    .to_field_value_pairs(request_id, global_id)
                     .change_context(RedisError::JsonSerializationFailed)?,
             )
             .await
diff --git a/crates/storage_impl/src/lookup.rs b/crates/storage_impl/src/lookup.rs
index dbfd77a8d6a0..bd045fedd379 100644
--- a/crates/storage_impl/src/lookup.rs
+++ b/crates/storage_impl/src/lookup.rs
@@ -135,7 +135,11 @@ impl<T: DatabaseStore> ReverseLookupInterface for KVRouterStore<T> {
                     .try_into_get()
                 };
 
-                try_redis_get_else_try_database_get(redis_fut, database_call).await
+                Box::pin(try_redis_get_else_try_database_get(
+                    redis_fut,
+                    database_call,
+                ))
+                .await
             }
         }
     }
diff --git a/crates/storage_impl/src/mock_db.rs b/crates/storage_impl/src/mock_db.rs
index 8674f7615684..4cdf8e2456bb 100644
--- a/crates/storage_impl/src/mock_db.rs
+++ b/crates/storage_impl/src/mock_db.rs
@@ -27,7 +27,6 @@ pub struct MockDb {
     pub customers: Arc<Mutex<Vec<store::Customer>>>,
     pub refunds: Arc<Mutex<Vec<store::Refund>>>,
     pub processes: Arc<Mutex<Vec<store::ProcessTracker>>>,
-    pub connector_response: Arc<Mutex<Vec<store::ConnectorResponse>>>,
     pub redis: Arc<RedisStore>,
     pub api_keys: Arc<Mutex<Vec<store::ApiKey>>>,
     pub ephemeral_keys: Arc<Mutex<Vec<store::EphemeralKey>>>,
@@ -41,6 +40,9 @@ pub struct MockDb {
     pub business_profiles: Arc<Mutex<Vec<crate::store::business_profile::BusinessProfile>>>,
     pub reverse_lookups: Arc<Mutex<Vec<store::ReverseLookup>>>,
     pub payment_link: Arc<Mutex<Vec<store::payment_link::PaymentLink>>>,
+    pub organizations: Arc<Mutex<Vec<store::organization::Organization>>>,
+    pub users: Arc<Mutex<Vec<store::user::User>>>,
+    pub user_roles: Arc<Mutex<Vec<store::user_role::UserRole>>>,
 }
 
 impl MockDb {
@@ -56,7 +58,6 @@ impl MockDb {
             customers: Default::default(),
             refunds: Default::default(),
             processes: Default::default(),
-            connector_response: Default::default(),
             redis: Arc::new(
                 RedisStore::new(redis)
                     .await
@@ -74,6 +75,9 @@ impl MockDb {
             business_profiles: Default::default(),
             reverse_lookups: Default::default(),
             payment_link: Default::default(),
+            organizations: Default::default(),
+            users: Default::default(),
+            user_roles: Default::default(),
         })
     }
 }
diff --git a/crates/storage_impl/src/mock_db/payment_attempt.rs b/crates/storage_impl/src/mock_db/payment_attempt.rs
index 8674fd711ac0..cb2f81daa797 100644
--- a/crates/storage_impl/src/mock_db/payment_attempt.rs
+++ b/crates/storage_impl/src/mock_db/payment_attempt.rs
@@ -140,8 +140,10 @@ impl PaymentAttemptInterface for MockDb {
             multiple_capture_count: payment_attempt.multiple_capture_count,
             connector_response_reference_id: None,
             amount_capturable: payment_attempt.amount_capturable,
-            surcharge_metadata: payment_attempt.surcharge_metadata,
             updated_by: storage_scheme.to_string(),
+            authentication_data: payment_attempt.authentication_data,
+            encoded_data: payment_attempt.encoded_data,
+            merchant_connector_id: payment_attempt.merchant_connector_id,
         };
         payment_attempts.push(payment_attempt.clone());
         Ok(payment_attempt)
diff --git a/crates/storage_impl/src/mock_db/payment_intent.rs b/crates/storage_impl/src/mock_db/payment_intent.rs
index edc17a0cf54a..08a4a2aabeaa 100644
--- a/crates/storage_impl/src/mock_db/payment_intent.rs
+++ b/crates/storage_impl/src/mock_db/payment_intent.rs
@@ -11,6 +11,7 @@ use diesel_models::enums as storage_enums;
 use error_stack::{IntoReport, ResultExt};
 
 use super::MockDb;
+use crate::DataModelExt;
 
 #[async_trait::async_trait]
 impl PaymentIntentInterface for MockDb {
@@ -104,6 +105,7 @@ impl PaymentIntentInterface for MockDb {
             payment_link_id: new.payment_link_id,
             payment_confirm_source: new.payment_confirm_source,
             updated_by: storage_scheme.to_string(),
+            surcharge_applicable: new.surcharge_applicable,
         };
         payment_intents.push(payment_intent.clone());
         Ok(payment_intent)
@@ -122,7 +124,11 @@ impl PaymentIntentInterface for MockDb {
             .iter_mut()
             .find(|item| item.id == this.id)
             .unwrap();
-        *payment_intent = update.apply_changeset(this);
+        *payment_intent = PaymentIntent::from_storage_model(
+            update
+                .to_storage_model()
+                .apply_changeset(this.to_storage_model()),
+        );
         Ok(payment_intent.clone())
     }
 
diff --git a/crates/storage_impl/src/payments/payment_attempt.rs b/crates/storage_impl/src/payments/payment_attempt.rs
index 518aaa2e3d92..3d00e2f2bf7a 100644
--- a/crates/storage_impl/src/payments/payment_attempt.rs
+++ b/crates/storage_impl/src/payments/payment_attempt.rs
@@ -360,8 +360,10 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
                     multiple_capture_count: payment_attempt.multiple_capture_count,
                     connector_response_reference_id: None,
                     amount_capturable: payment_attempt.amount_capturable,
-                    surcharge_metadata: payment_attempt.surcharge_metadata.clone(),
                     updated_by: storage_scheme.to_string(),
+                    authentication_data: payment_attempt.authentication_data.clone(),
+                    encoded_data: payment_attempt.encoded_data.clone(),
+                    merchant_connector_id: payment_attempt.merchant_connector_id.clone(),
                 };
 
                 let field = format!("pa_{}", created_attempt.attempt_id);
@@ -555,12 +557,12 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
                     .await?;
                 let key = &lookup.pk_id;
 
-                try_redis_get_else_try_database_get(
+                Box::pin(try_redis_get_else_try_database_get(
                     async {
                         kv_wrapper(self, KvOperation::<DieselPaymentAttempt>::HGet(&lookup.sk_id), key).await?.try_into_hget()
                     },
                         || async {self.router_store.find_payment_attempt_by_connector_transaction_id_payment_id_merchant_id(connector_transaction_id, payment_id, merchant_id, storage_scheme).await},
-                    )
+                    ))
                     .await
             }
         }
@@ -605,7 +607,11 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
                             ))
                     })
                 };
-                try_redis_get_else_try_database_get(redis_fut, database_call).await
+                Box::pin(try_redis_get_else_try_database_get(
+                    redis_fut,
+                    database_call,
+                ))
+                .await
             }
         }
     }
@@ -633,7 +639,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
                     .await?;
 
                 let key = &lookup.pk_id;
-                try_redis_get_else_try_database_get(
+                Box::pin(try_redis_get_else_try_database_get(
                     async {
                         kv_wrapper(
                             self,
@@ -652,7 +658,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
                             )
                             .await
                     },
-                )
+                ))
                 .await
             }
         }
@@ -680,7 +686,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
             MerchantStorageScheme::RedisKv => {
                 let key = format!("mid_{merchant_id}_pid_{payment_id}");
                 let field = format!("pa_{attempt_id}");
-                try_redis_get_else_try_database_get(
+                Box::pin(try_redis_get_else_try_database_get(
                     async {
                         kv_wrapper(self, KvOperation::<DieselPaymentAttempt>::HGet(&field), key)
                             .await?
@@ -696,7 +702,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
                             )
                             .await
                     },
-                )
+                ))
                 .await
             }
         }
@@ -724,7 +730,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
                     .get_lookup_by_lookup_id(&lookup_id, storage_scheme)
                     .await?;
                 let key = &lookup.pk_id;
-                try_redis_get_else_try_database_get(
+                Box::pin(try_redis_get_else_try_database_get(
                     async {
                         kv_wrapper(
                             self,
@@ -743,7 +749,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
                             )
                             .await
                     },
-                )
+                ))
                 .await
             }
         }
@@ -772,7 +778,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
                     .await?;
                 let key = &lookup.pk_id;
 
-                try_redis_get_else_try_database_get(
+                Box::pin(try_redis_get_else_try_database_get(
                     async {
                         kv_wrapper(
                             self,
@@ -791,7 +797,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
                             )
                             .await
                     },
-                )
+                ))
                 .await
             }
         }
@@ -956,8 +962,10 @@ impl DataModelExt for PaymentAttempt {
             multiple_capture_count: self.multiple_capture_count,
             connector_response_reference_id: self.connector_response_reference_id,
             amount_capturable: self.amount_capturable,
-            surcharge_metadata: self.surcharge_metadata,
             updated_by: self.updated_by,
+            authentication_data: self.authentication_data,
+            encoded_data: self.encoded_data,
+            merchant_connector_id: self.merchant_connector_id,
         }
     }
 
@@ -1006,8 +1014,10 @@ impl DataModelExt for PaymentAttempt {
             multiple_capture_count: storage_model.multiple_capture_count,
             connector_response_reference_id: storage_model.connector_response_reference_id,
             amount_capturable: storage_model.amount_capturable,
-            surcharge_metadata: storage_model.surcharge_metadata,
             updated_by: storage_model.updated_by,
+            authentication_data: storage_model.authentication_data,
+            encoded_data: storage_model.encoded_data,
+            merchant_connector_id: storage_model.merchant_connector_id,
         }
     }
 }
@@ -1056,8 +1066,10 @@ impl DataModelExt for PaymentAttemptNew {
             connector_response_reference_id: self.connector_response_reference_id,
             multiple_capture_count: self.multiple_capture_count,
             amount_capturable: self.amount_capturable,
-            surcharge_metadata: self.surcharge_metadata,
             updated_by: self.updated_by,
+            authentication_data: self.authentication_data,
+            encoded_data: self.encoded_data,
+            merchant_connector_id: self.merchant_connector_id,
         }
     }
 
@@ -1104,8 +1116,10 @@ impl DataModelExt for PaymentAttemptNew {
             connector_response_reference_id: storage_model.connector_response_reference_id,
             multiple_capture_count: storage_model.multiple_capture_count,
             amount_capturable: storage_model.amount_capturable,
-            surcharge_metadata: storage_model.surcharge_metadata,
             updated_by: storage_model.updated_by,
+            authentication_data: storage_model.authentication_data,
+            encoded_data: storage_model.encoded_data,
+            merchant_connector_id: storage_model.merchant_connector_id,
         }
     }
 }
@@ -1128,6 +1142,8 @@ impl DataModelExt for PaymentAttemptUpdate {
                 business_sub_label,
                 amount_to_capture,
                 capture_method,
+                surcharge_amount,
+                tax_amount,
                 updated_by,
             } => DieselPaymentAttemptUpdate::Update {
                 amount,
@@ -1142,6 +1158,8 @@ impl DataModelExt for PaymentAttemptUpdate {
                 business_sub_label,
                 amount_to_capture,
                 capture_method,
+                surcharge_amount,
+                tax_amount,
                 updated_by,
             },
             Self::UpdateTrackers {
@@ -1150,12 +1168,18 @@ impl DataModelExt for PaymentAttemptUpdate {
                 straight_through_algorithm,
                 amount_capturable,
                 updated_by,
+                surcharge_amount,
+                tax_amount,
+                merchant_connector_id,
             } => DieselPaymentAttemptUpdate::UpdateTrackers {
                 payment_token,
                 connector,
                 straight_through_algorithm,
                 amount_capturable,
+                surcharge_amount,
+                tax_amount,
                 updated_by,
+                merchant_connector_id,
             },
             Self::AuthenticationTypeUpdate {
                 authentication_type,
@@ -1181,9 +1205,8 @@ impl DataModelExt for PaymentAttemptUpdate {
                 error_code,
                 error_message,
                 amount_capturable,
-                surcharge_amount,
-                tax_amount,
                 updated_by,
+                merchant_connector_id: connector_id,
             } => DieselPaymentAttemptUpdate::ConfirmUpdate {
                 amount,
                 currency,
@@ -1201,9 +1224,8 @@ impl DataModelExt for PaymentAttemptUpdate {
                 error_code,
                 error_message,
                 amount_capturable,
-                surcharge_amount,
-                tax_amount,
                 updated_by,
+                merchant_connector_id: connector_id,
             },
             Self::VoidUpdate {
                 status,
@@ -1229,6 +1251,10 @@ impl DataModelExt for PaymentAttemptUpdate {
                 connector_response_reference_id,
                 amount_capturable,
                 updated_by,
+                surcharge_amount,
+                tax_amount,
+                authentication_data,
+                encoded_data,
             } => DieselPaymentAttemptUpdate::ResponseUpdate {
                 status,
                 connector,
@@ -1244,6 +1270,10 @@ impl DataModelExt for PaymentAttemptUpdate {
                 connector_response_reference_id,
                 amount_capturable,
                 updated_by,
+                surcharge_amount,
+                tax_amount,
+                authentication_data,
+                encoded_data,
             },
             Self::UnresolvedResponseUpdate {
                 status,
@@ -1330,11 +1360,17 @@ impl DataModelExt for PaymentAttemptUpdate {
                 amount_capturable,
                 updated_by,
             },
-            Self::SurchargeMetadataUpdate {
-                surcharge_metadata,
+            Self::ConnectorResponse {
+                authentication_data,
+                encoded_data,
+                connector_transaction_id,
+                connector,
                 updated_by,
-            } => DieselPaymentAttemptUpdate::SurchargeMetadataUpdate {
-                surcharge_metadata,
+            } => DieselPaymentAttemptUpdate::ConnectorResponse {
+                authentication_data,
+                encoded_data,
+                connector_transaction_id,
+                connector,
                 updated_by,
             },
         }
@@ -1355,6 +1391,8 @@ impl DataModelExt for PaymentAttemptUpdate {
                 business_sub_label,
                 amount_to_capture,
                 capture_method,
+                surcharge_amount,
+                tax_amount,
                 updated_by,
             } => Self::Update {
                 amount,
@@ -1369,6 +1407,8 @@ impl DataModelExt for PaymentAttemptUpdate {
                 business_sub_label,
                 amount_to_capture,
                 capture_method,
+                surcharge_amount,
+                tax_amount,
                 updated_by,
             },
             DieselPaymentAttemptUpdate::UpdateTrackers {
@@ -1377,12 +1417,18 @@ impl DataModelExt for PaymentAttemptUpdate {
                 straight_through_algorithm,
                 amount_capturable,
                 updated_by,
+                surcharge_amount,
+                tax_amount,
+                merchant_connector_id: connector_id,
             } => Self::UpdateTrackers {
                 payment_token,
                 connector,
                 straight_through_algorithm,
                 amount_capturable,
+                surcharge_amount,
+                tax_amount,
                 updated_by,
+                merchant_connector_id: connector_id,
             },
             DieselPaymentAttemptUpdate::AuthenticationTypeUpdate {
                 authentication_type,
@@ -1408,9 +1454,8 @@ impl DataModelExt for PaymentAttemptUpdate {
                 error_code,
                 error_message,
                 amount_capturable,
-                surcharge_amount,
-                tax_amount,
                 updated_by,
+                merchant_connector_id: connector_id,
             } => Self::ConfirmUpdate {
                 amount,
                 currency,
@@ -1428,9 +1473,8 @@ impl DataModelExt for PaymentAttemptUpdate {
                 error_code,
                 error_message,
                 amount_capturable,
-                surcharge_amount,
-                tax_amount,
                 updated_by,
+                merchant_connector_id: connector_id,
             },
             DieselPaymentAttemptUpdate::VoidUpdate {
                 status,
@@ -1456,6 +1500,10 @@ impl DataModelExt for PaymentAttemptUpdate {
                 connector_response_reference_id,
                 amount_capturable,
                 updated_by,
+                surcharge_amount,
+                tax_amount,
+                authentication_data,
+                encoded_data,
             } => Self::ResponseUpdate {
                 status,
                 connector,
@@ -1471,6 +1519,10 @@ impl DataModelExt for PaymentAttemptUpdate {
                 connector_response_reference_id,
                 amount_capturable,
                 updated_by,
+                surcharge_amount,
+                tax_amount,
+                authentication_data,
+                encoded_data,
             },
             DieselPaymentAttemptUpdate::UnresolvedResponseUpdate {
                 status,
@@ -1557,11 +1609,17 @@ impl DataModelExt for PaymentAttemptUpdate {
                 amount_capturable,
                 updated_by,
             },
-            DieselPaymentAttemptUpdate::SurchargeMetadataUpdate {
-                surcharge_metadata,
+            DieselPaymentAttemptUpdate::ConnectorResponse {
+                authentication_data,
+                encoded_data,
+                connector_transaction_id,
+                connector,
                 updated_by,
-            } => Self::SurchargeMetadataUpdate {
-                surcharge_metadata,
+            } => Self::ConnectorResponse {
+                authentication_data,
+                encoded_data,
+                connector_transaction_id,
+                connector,
                 updated_by,
             },
         }
diff --git a/crates/storage_impl/src/payments/payment_intent.rs b/crates/storage_impl/src/payments/payment_intent.rs
index e1149098ec4e..c3b3d22ffe35 100644
--- a/crates/storage_impl/src/payments/payment_intent.rs
+++ b/crates/storage_impl/src/payments/payment_intent.rs
@@ -39,7 +39,7 @@ use crate::connection;
 use crate::{
     diesel_error_to_data_error,
     redis::kv_store::{kv_wrapper, KvOperation},
-    utils::{pg_connection_read, pg_connection_write},
+    utils::{self, pg_connection_read, pg_connection_write},
     DataModelExt, DatabaseStore, KVRouterStore,
 };
 
@@ -96,6 +96,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
                     payment_link_id: new.payment_link_id.clone(),
                     payment_confirm_source: new.payment_confirm_source,
                     updated_by: storage_scheme.to_string(),
+                    surcharge_applicable: new.surcharge_applicable,
                 };
                 let redis_entry = kv::TypedSql {
                     op: kv::DBOperation::Insert {
@@ -145,8 +146,12 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
                 let key = format!("mid_{}_pid_{}", this.merchant_id, this.payment_id);
                 let field = format!("pi_{}", this.payment_id);
 
-                let updated_intent = payment_intent_update.clone().apply_changeset(this.clone());
-                let diesel_intent = updated_intent.clone().to_storage_model();
+                let diesel_intent_update = payment_intent_update.to_storage_model();
+                let origin_diesel_intent = this.to_storage_model();
+
+                let diesel_intent = diesel_intent_update
+                    .clone()
+                    .apply_changeset(origin_diesel_intent.clone());
                 // Check for database presence as well Maybe use a read replica here ?
 
                 let redis_value =
@@ -157,8 +162,8 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
                     op: kv::DBOperation::Update {
                         updatable: kv::Updateable::PaymentIntentUpdate(
                             kv::PaymentIntentUpdateMems {
-                                orig: this.to_storage_model(),
-                                update_data: payment_intent_update.to_storage_model(),
+                                orig: origin_diesel_intent,
+                                update_data: diesel_intent_update,
                             },
                         ),
                     },
@@ -174,7 +179,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
                 .try_into_hset()
                 .change_context(StorageError::KVError)?;
 
-                Ok(updated_intent)
+                Ok(PaymentIntent::from_storage_model(diesel_intent))
             }
         }
     }
@@ -201,7 +206,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
             MerchantStorageScheme::RedisKv => {
                 let key = format!("mid_{merchant_id}_pid_{payment_id}");
                 let field = format!("pi_{payment_id}");
-                crate::utils::try_redis_get_else_try_database_get(
+                Box::pin(utils::try_redis_get_else_try_database_get(
                     async {
                         kv_wrapper::<DieselPaymentIntent, _, _>(
                             self,
@@ -212,7 +217,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
                         .try_into_hget()
                     },
                     database_call,
-                )
+                ))
                 .await
             }
         }
@@ -752,6 +757,7 @@ impl DataModelExt for PaymentIntentNew {
             payment_link_id: self.payment_link_id,
             payment_confirm_source: self.payment_confirm_source,
             updated_by: self.updated_by,
+            surcharge_applicable: self.surcharge_applicable,
         }
     }
 
@@ -791,6 +797,7 @@ impl DataModelExt for PaymentIntentNew {
             payment_link_id: storage_model.payment_link_id,
             payment_confirm_source: storage_model.payment_confirm_source,
             updated_by: storage_model.updated_by,
+            surcharge_applicable: storage_model.surcharge_applicable,
         }
     }
 }
@@ -835,6 +842,7 @@ impl DataModelExt for PaymentIntent {
             payment_link_id: self.payment_link_id,
             payment_confirm_source: self.payment_confirm_source,
             updated_by: self.updated_by,
+            surcharge_applicable: self.surcharge_applicable,
         }
     }
 
@@ -875,6 +883,7 @@ impl DataModelExt for PaymentIntent {
             payment_link_id: storage_model.payment_link_id,
             payment_confirm_source: storage_model.payment_confirm_source,
             updated_by: storage_model.updated_by,
+            surcharge_applicable: storage_model.surcharge_applicable,
         }
     }
 }
@@ -1004,6 +1013,13 @@ impl DataModelExt for PaymentIntentUpdate {
                 merchant_decision,
                 updated_by,
             },
+            Self::SurchargeApplicableUpdate {
+                surcharge_applicable,
+                updated_by,
+            } => DieselPaymentIntentUpdate::SurchargeApplicableUpdate {
+                surcharge_applicable: Some(surcharge_applicable),
+                updated_by,
+            },
         }
     }
 
diff --git a/crates/storage_impl/src/redis/kv_store.rs b/crates/storage_impl/src/redis/kv_store.rs
index 32fe21f758a3..3eadd8b83ade 100644
--- a/crates/storage_impl/src/redis/kv_store.rs
+++ b/crates/storage_impl/src/redis/kv_store.rs
@@ -6,7 +6,7 @@ use router_derive::TryGetEnumVariant;
 use router_env::logger;
 use serde::de;
 
-use crate::{consts, metrics, store::kv::TypedSql, KVRouterStore};
+use crate::{metrics, store::kv::TypedSql, KVRouterStore};
 
 pub trait KvStorePartition {
     fn partition_number(key: PartitionKey<'_>, num_partitions: u8) -> u32 {
@@ -102,15 +102,17 @@ where
     let type_name = std::any::type_name::<T>();
     let operation = op.to_string();
 
+    let ttl = store.ttl_for_kv;
+
     let partition_key = PartitionKey::MerchantIdPaymentIdCombination { combination: key };
 
     let result = async {
         match op {
             KvOperation::Hset(value, sql) => {
-                logger::debug!("Operation: {operation} value: {value:?}");
+                logger::debug!(kv_operation= %operation, value = ?value);
 
                 redis_conn
-                    .set_hash_fields(key, value, Some(consts::KV_TTL))
+                    .set_hash_fields(key, value, Some(ttl.into()))
                     .await?;
 
                 store
@@ -133,15 +135,10 @@ where
             }
 
             KvOperation::HSetNx(field, value, sql) => {
-                logger::debug!("Operation: {operation} value: {value:?}");
+                logger::debug!(kv_operation= %operation, value = ?value);
 
                 let result = redis_conn
-                    .serialize_and_set_hash_field_if_not_exist(
-                        key,
-                        field,
-                        value,
-                        Some(consts::KV_TTL),
-                    )
+                    .serialize_and_set_hash_field_if_not_exist(key, field, value, Some(ttl))
                     .await?;
 
                 if matches!(result, redis_interface::HsetnxReply::KeySet) {
@@ -153,10 +150,10 @@ where
             }
 
             KvOperation::SetNx(value, sql) => {
-                logger::debug!("Operation: {operation} value: {value:?}");
+                logger::debug!(kv_operation= %operation, value = ?value);
 
                 let result = redis_conn
-                    .serialize_and_set_key_if_not_exist(key, value, Some(consts::KV_TTL.into()))
+                    .serialize_and_set_key_if_not_exist(key, value, Some(ttl.into()))
                     .await?;
 
                 if matches!(result, redis_interface::SetnxReply::KeySet) {
@@ -178,14 +175,14 @@ where
     result
         .await
         .map(|result| {
-            logger::debug!("KvOperation {operation} succeeded");
+            logger::debug!(kv_operation= %operation, status="success");
             let keyvalue = router_env::opentelemetry::KeyValue::new("operation", operation.clone());
 
             metrics::KV_OPERATION_SUCCESSFUL.add(&metrics::CONTEXT, 1, &[keyvalue]);
             result
         })
         .map_err(|err| {
-            logger::error!("KvOperation for {operation} failed with {err:?}");
+            logger::error!(kv_operation = %operation, status="error", error = ?err);
             let keyvalue = router_env::opentelemetry::KeyValue::new("operation", operation);
 
             metrics::KV_OPERATION_FAILED.add(&metrics::CONTEXT, 1, &[keyvalue]);
diff --git a/crates/test_utils/Cargo.toml b/crates/test_utils/Cargo.toml
index 44c835b21623..957a51171da7 100644
--- a/crates/test_utils/Cargo.toml
+++ b/crates/test_utils/Cargo.toml
@@ -9,30 +9,23 @@ license.workspace = true
 
 [features]
 default = ["dummy_connector", "payouts"]
-dummy_connector = ["api_models/dummy_connector"]
+dummy_connector = []
 payouts = []
 
 [dependencies]
 async-trait = "0.1.68"
-actix-web = "4.3.1"
 base64 = "0.21.2"
 clap = { version = "4.3.2", default-features = false, features = ["std", "derive", "help", "usage"] }
+rand = "0.8.5"
+reqwest = { version = "0.11.18", features = ["native-tls"] }
 serde = { version = "1.0.163", features = ["derive"] }
 serde_json = "1.0.96"
-serde_path_to_error = "0.1.11"
-toml = "0.7.4"
-serial_test = "2.0.0"
 serde_urlencoded = "0.7.1"
-actix-http = "3.3.1"
-awc = { version = "3.1.1", features = ["rustls"] }
-derive_deref = "1.1.1"
-rand = "0.8.5"
-reqwest = { version = "0.11.18", features = ["native-tls"] }
+serial_test = "2.0.0"
 thirtyfour = "0.31.0"
 time = { version = "0.3.21", features = ["macros"] }
 tokio = "1.28.2"
-uuid = { version = "1.3.3", features = ["serde", "v4"] }
+toml = "0.7.4"
 
 # First party crates
-api_models = { version = "0.1.0", path = "../api_models", features = ["errors"] }
 masking = { version = "0.1.0", path = "../masking" }
diff --git a/crates/test_utils/README.md b/crates/test_utils/README.md
index 1e92174b3337..2edbc7104c25 100644
--- a/crates/test_utils/README.md
+++ b/crates/test_utils/README.md
@@ -28,9 +28,16 @@ Required fields:
 
 Optional fields:
 
+- `--delay` -- To add a delay between requests in milliseconds.
+  - Maximum delay is 4294967295 milliseconds or 4294967.295 seconds or 71616 minutes or 1193.6 hours or 49.733 days
+  - Example: `--delay 1000` (for 1 second delay)
 - `--folder` -- To run individual folders in the collection
   - Use double quotes to specify folder name. If you wish to run multiple folders, separate them with a comma (`,`)
   - Example: `--folder "QuickStart"` or `--folder "Health check,QuickStart"`
+- `--header` -- If you wish to add custom headers to the requests, you can pass them as a string
+  - Example: `--header "key:value"`
+  - If you want to pass multiple custom headers, you can pass multiple `--header` flags
+    - Example: `--header "key1:value1" --header "key2:value2"`
 - `--verbose` -- A boolean to print detailed logs (requests and responses)
 
 **Note:** Passing `--verbose` will also print the connector as well as admin API keys in the logs. So, make sure you don't push the commands with `--verbose` to any public repository.
diff --git a/crates/test_utils/src/connector_auth.rs b/crates/test_utils/src/connector_auth.rs
index d774e2530e9d..9562972c126e 100644
--- a/crates/test_utils/src/connector_auth.rs
+++ b/crates/test_utils/src/connector_auth.rs
@@ -17,6 +17,7 @@ pub struct ConnectorAuthentication {
     pub airwallex: Option<BodyKey>,
     pub authorizedotnet: Option<BodyKey>,
     pub bambora: Option<BodyKey>,
+    pub bankofamerica: Option<SignatureKey>,
     pub bitpay: Option<HeaderKey>,
     pub bluesnap: Option<BodyKey>,
     pub boku: Option<BodyKey>,
diff --git a/crates/test_utils/src/main.rs b/crates/test_utils/src/main.rs
index 637122e468e6..22c91e063d8f 100644
--- a/crates/test_utils/src/main.rs
+++ b/crates/test_utils/src/main.rs
@@ -3,10 +3,10 @@ use std::process::{exit, Command};
 use test_utils::newman_runner;
 
 fn main() {
-    let mut newman_command: Command = newman_runner::command_generate();
+    let mut runner = newman_runner::generate_newman_command();
 
     // Execute the newman command
-    let output = newman_command.spawn();
+    let output = runner.newman_command.spawn();
     let mut child = match output {
         Ok(child) => child,
         Err(err) => {
@@ -16,6 +16,30 @@ fn main() {
     };
     let status = child.wait();
 
+    if runner.file_modified_flag {
+        let git_status = Command::new("git")
+            .args([
+                "restore",
+                format!("{}/event.prerequest.js", runner.collection_path).as_str(),
+            ])
+            .output();
+
+        match git_status {
+            Ok(output) => {
+                if output.status.success() {
+                    let stdout_str = String::from_utf8_lossy(&output.stdout);
+                    println!("Git command executed successfully: {stdout_str}");
+                } else {
+                    let stderr_str = String::from_utf8_lossy(&output.stderr);
+                    eprintln!("Git command failed with error: {stderr_str}");
+                }
+            }
+            Err(e) => {
+                eprintln!("Error running Git: {e}");
+            }
+        }
+    }
+
     let exit_code = match status {
         Ok(exit_status) => {
             if exit_status.success() {
diff --git a/crates/test_utils/src/newman_runner.rs b/crates/test_utils/src/newman_runner.rs
index c51556f8f255..a6e0268e2c29 100644
--- a/crates/test_utils/src/newman_runner.rs
+++ b/crates/test_utils/src/newman_runner.rs
@@ -1,22 +1,28 @@
-use std::{env, process::Command};
+use std::{env, io::Write, path::Path, process::Command};
 
 use clap::{arg, command, Parser};
 use masking::PeekInterface;
 
 use crate::connector_auth::{ConnectorAuthType, ConnectorAuthenticationMap};
-
 #[derive(Parser)]
 #[command(version, about = "Postman collection runner using newman!", long_about = None)]
 struct Args {
     /// Admin API Key of the environment
-    #[arg(short, long = "admin_api_key")]
+    #[arg(short, long)]
     admin_api_key: String,
     /// Base URL of the Hyperswitch environment
-    #[arg(short, long = "base_url")]
+    #[arg(short, long)]
     base_url: String,
     /// Name of the connector
-    #[arg(short, long = "connector_name")]
+    #[arg(short, long)]
     connector_name: String,
+    /// Custom headers
+    #[arg(short = 'H', long = "header")]
+    custom_headers: Option<Vec<String>>,
+    /// Minimum delay in milliseconds to be added before sending a request
+    /// By default, 7 milliseconds will be the delay
+    #[arg(short, long, default_value_t = 7)]
+    delay_request: u32,
     /// Folder name of specific tests
     #[arg(short, long = "folder")]
     folders: Option<String>,
@@ -25,6 +31,12 @@ struct Args {
     verbose: bool,
 }
 
+pub struct ReturnArgs {
+    pub newman_command: Command,
+    pub file_modified_flag: bool,
+    pub collection_path: String,
+}
+
 // Just by the name of the connector, this function generates the name of the collection dir
 // Example: CONNECTOR_NAME="stripe" -> OUTPUT: postman/collection-dir/stripe
 #[inline]
@@ -32,7 +44,29 @@ fn get_path(name: impl AsRef<str>) -> String {
     format!("postman/collection-dir/{}", name.as_ref())
 }
 
-pub fn command_generate() -> Command {
+// This function currently allows you to add only custom headers.
+// In future, as we scale, this can be modified based on the need
+fn insert_content<T, U>(dir: T, content_to_insert: U) -> std::io::Result<()>
+where
+    T: AsRef<Path>,
+    U: AsRef<str>,
+{
+    let file_name = "event.prerequest.js";
+    let file_path = dir.as_ref().join(file_name);
+
+    // Open the file in write mode or create it if it doesn't exist
+    let mut file = std::fs::OpenOptions::new()
+        .write(true)
+        .append(true)
+        .create(true)
+        .open(file_path)?;
+
+    write!(file, "{}", content_to_insert.as_ref())?;
+
+    Ok(())
+}
+
+pub fn generate_newman_command() -> ReturnArgs {
     let args = Args::parse();
 
     let connector_name = args.connector_name;
@@ -129,7 +163,10 @@ pub fn command_generate() -> Command {
         ]);
     }
 
-    newman_command.arg("--delay-request").arg("7"); // 7 milli seconds delay
+    newman_command.args([
+        "--delay-request",
+        format!("{}", &args.delay_request).as_str(),
+    ]);
 
     newman_command.arg("--color").arg("on");
 
@@ -151,5 +188,24 @@ pub fn command_generate() -> Command {
         newman_command.arg("--verbose");
     }
 
-    newman_command
+    let mut modified = false;
+    if let Some(headers) = &args.custom_headers {
+        for header in headers {
+            if let Some((key, value)) = header.split_once(':') {
+                let content_to_insert =
+                    format!(r#"pm.request.headers.add({{key: "{key}", value: "{value}"}});"#);
+                if insert_content(&collection_path, &content_to_insert).is_ok() {
+                    modified = true;
+                }
+            } else {
+                eprintln!("Invalid header format: {}", header);
+            }
+        }
+    }
+
+    ReturnArgs {
+        newman_command,
+        file_modified_flag: modified,
+        collection_path,
+    }
 }
diff --git a/docker-compose.yml b/docker-compose.yml
index 1fe487da5aab..f4dce575132e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -72,7 +72,7 @@ services:
   pg:
     image: postgres:14.5
     ports:
-      - "5432"
+      - "5432:5432"
     networks:
       - router_net
     volumes:
diff --git a/docs/imgs/aws_button.png b/docs/imgs/aws_button.png
new file mode 100644
index 000000000000..4c8c2c20e097
Binary files /dev/null and b/docs/imgs/aws_button.png differ
diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml
index 47235601cb0e..f70fc656d8e3 100644
--- a/loadtest/config/development.toml
+++ b/loadtest/config/development.toml
@@ -32,7 +32,6 @@ jwt_secret = "secret"
 host = ""
 mock_locker = true
 basilisk_host = ""
-redis_temp_locker_encryption_key = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"
 
 [eph_key]
 validity = 1
@@ -65,6 +64,7 @@ airwallex.base_url = "https://api-demo.airwallex.com/"
 applepay.base_url = "https://apple-pay-gateway.apple.com/"
 authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api"
 bambora.base_url = "https://api.na.bambora.com"
+bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/"
 bitpay.base_url = "https://test.bitpay.com"
 bluesnap.base_url = "https://sandbox.bluesnap.com/"
 bluesnap.secondary_base_url = "https://sandpay.bluesnap.com/"
@@ -131,6 +131,7 @@ cards = [
     "airwallex",
     "authorizedotnet",
     "bambora",
+    "bankofamerica",
     "bitpay",
     "bluesnap",
     "boku",
@@ -235,3 +236,18 @@ card.debit = {connector_list = "stripe,adyen,authorizedotnet,globalpay,worldpay,
 bank_debit.ach = { connector_list = "gocardless"}
 bank_debit.becs = { connector_list = "gocardless"}
 bank_debit.sepa = { connector_list = "gocardless"}
+
+[analytics]
+source = "sqlx"
+
+[analytics.sqlx]
+username = "db_user"
+password = "db_pass"
+host = "localhost"
+port = 5432
+dbname = "hyperswitch_db"
+pool_size = 5
+connection_timeout = 10
+
+[kv_config]
+ttl = 300 # 5 * 60 seconds
diff --git a/migrations/2023-10-19-071731_add_connector_id_to_payment_attempt/down.sql b/migrations/2023-10-19-071731_add_connector_id_to_payment_attempt/down.sql
new file mode 100644
index 000000000000..993bba9f05d5
--- /dev/null
+++ b/migrations/2023-10-19-071731_add_connector_id_to_payment_attempt/down.sql
@@ -0,0 +1,2 @@
+-- This file should undo anything in `up.sql`
+ALTER TABLE payment_attempt DROP COLUMN IF EXISTS connector_id;
diff --git a/migrations/2023-10-19-071731_add_connector_id_to_payment_attempt/up.sql b/migrations/2023-10-19-071731_add_connector_id_to_payment_attempt/up.sql
new file mode 100644
index 000000000000..ed475a93113a
--- /dev/null
+++ b/migrations/2023-10-19-071731_add_connector_id_to_payment_attempt/up.sql
@@ -0,0 +1,5 @@
+-- Your SQL goes here
+-- The type is VARCHAR(32) as this will store the merchant_connector_account id
+-- which will be generated by the application using default length
+ALTER TABLE payment_attempt
+ADD COLUMN IF NOT EXISTS merchant_connector_id VARCHAR(32);
diff --git a/migrations/2023-10-19-075810_add_surcharge_applicable_payment_intent/down.sql b/migrations/2023-10-19-075810_add_surcharge_applicable_payment_intent/down.sql
new file mode 100644
index 000000000000..8d4394202e1b
--- /dev/null
+++ b/migrations/2023-10-19-075810_add_surcharge_applicable_payment_intent/down.sql
@@ -0,0 +1,5 @@
+ALTER TABLE payment_attempt
+ADD COLUMN IF NOT EXISTS surcharge_metadata JSONB DEFAULT NULL;
+
+ALTER TABLE payment_intent
+DROP COLUMN surcharge_applicable;
diff --git a/migrations/2023-10-19-075810_add_surcharge_applicable_payment_intent/up.sql b/migrations/2023-10-19-075810_add_surcharge_applicable_payment_intent/up.sql
new file mode 100644
index 000000000000..8d5730ba098e
--- /dev/null
+++ b/migrations/2023-10-19-075810_add_surcharge_applicable_payment_intent/up.sql
@@ -0,0 +1,6 @@
+ALTER TABLE payment_attempt
+DROP COLUMN surcharge_metadata;
+
+
+ALTER TABLE payment_intent
+ADD surcharge_applicable boolean;
\ No newline at end of file
diff --git a/migrations/2023-10-19-101558_create_routing_algorithm_table/down.sql b/migrations/2023-10-19-101558_create_routing_algorithm_table/down.sql
new file mode 100644
index 000000000000..2cace88297db
--- /dev/null
+++ b/migrations/2023-10-19-101558_create_routing_algorithm_table/down.sql
@@ -0,0 +1,4 @@
+-- This file should undo anything in `up.sql`
+
+DROP TABLE routing_algorithm;
+DROP TYPE "RoutingAlgorithmKind";
diff --git a/migrations/2023-10-19-101558_create_routing_algorithm_table/up.sql b/migrations/2023-10-19-101558_create_routing_algorithm_table/up.sql
new file mode 100644
index 000000000000..361194561227
--- /dev/null
+++ b/migrations/2023-10-19-101558_create_routing_algorithm_table/up.sql
@@ -0,0 +1,19 @@
+-- Your SQL goes here
+
+CREATE TYPE "RoutingAlgorithmKind" AS ENUM ('single', 'priority', 'volume_split', 'advanced');
+
+CREATE TABLE routing_algorithm (
+    algorithm_id VARCHAR(64) PRIMARY KEY,
+    profile_id VARCHAR(64) NOT NULL,
+    merchant_id VARCHAR(64) NOT NULL,
+    name VARCHAR(64) NOT NULL,
+    description VARCHAR(256),
+    kind "RoutingAlgorithmKind" NOT NULL,
+    algorithm_data JSONB NOT NULL,
+    created_at TIMESTAMP NOT NULL,
+    modified_at TIMESTAMP NOT NULL
+);
+
+CREATE INDEX routing_algorithm_profile_id_modified_at ON routing_algorithm (profile_id, modified_at DESC);
+
+CREATE INDEX routing_algorithm_merchant_id_modified_at ON routing_algorithm (merchant_id, modified_at DESC);
diff --git a/migrations/2023-10-19-102636_back_fill_n_remove_connector_response/down.sql b/migrations/2023-10-19-102636_back_fill_n_remove_connector_response/down.sql
new file mode 100644
index 000000000000..7d14e420e90c
--- /dev/null
+++ b/migrations/2023-10-19-102636_back_fill_n_remove_connector_response/down.sql
@@ -0,0 +1,2 @@
+
+ALTER TABLE payment_attempt DROP COLUMN authentication_data, DROP COLUMN encoded_data;
diff --git a/migrations/2023-10-19-102636_back_fill_n_remove_connector_response/up.sql b/migrations/2023-10-19-102636_back_fill_n_remove_connector_response/up.sql
new file mode 100644
index 000000000000..e80d4db1b4c0
--- /dev/null
+++ b/migrations/2023-10-19-102636_back_fill_n_remove_connector_response/up.sql
@@ -0,0 +1,11 @@
+-- Your SQL goes here
+ALTER TABLE payment_attempt 
+ADD COLUMN authentication_data JSON, 
+ADD COLUMN encoded_data TEXT;
+
+UPDATE payment_attempt 
+SET (authentication_data, encoded_data) = (connector_response.authentication_data, connector_response.encoded_data) 
+from connector_response 
+where payment_attempt.payment_id = connector_response.payment_id 
+    and payment_attempt.attempt_id = connector_response.attempt_id
+    and payment_attempt.merchant_id = connector_response.merchant_id;
diff --git a/migrations/2023-10-19-124023_add_connector_id_to_other_tables/down.sql b/migrations/2023-10-19-124023_add_connector_id_to_other_tables/down.sql
new file mode 100644
index 000000000000..8bb1a2b8e394
--- /dev/null
+++ b/migrations/2023-10-19-124023_add_connector_id_to_other_tables/down.sql
@@ -0,0 +1,10 @@
+-- This file should undo anything in `up.sql`
+ALTER TABLE file_metadata DROP COLUMN IF EXISTS merchant_connector_id;
+
+ALTER TABLE refund DROP COLUMN IF EXISTS merchant_connector_id;
+
+ALTER TABLE payout_attempt DROP COLUMN IF EXISTS merchant_connector_id;
+
+ALTER TABLE dispute DROP COLUMN IF EXISTS merchant_connector_id;
+
+ALTER TABLE mandate DROP COLUMN IF EXISTS merchant_connector_id;
diff --git a/migrations/2023-10-19-124023_add_connector_id_to_other_tables/up.sql b/migrations/2023-10-19-124023_add_connector_id_to_other_tables/up.sql
new file mode 100644
index 000000000000..42de0188f36b
--- /dev/null
+++ b/migrations/2023-10-19-124023_add_connector_id_to_other_tables/up.sql
@@ -0,0 +1,15 @@
+-- Your SQL goes here
+ALTER TABLE file_metadata
+ADD COLUMN IF NOT EXISTS merchant_connector_id VARCHAR(32);
+
+ALTER TABLE refund
+ADD COLUMN IF NOT EXISTS merchant_connector_id VARCHAR(32);
+
+ALTER TABLE payout_attempt
+ADD COLUMN IF NOT EXISTS merchant_connector_id VARCHAR(32);
+
+ALTER TABLE dispute
+ADD COLUMN IF NOT EXISTS merchant_connector_id VARCHAR(32);
+
+ALTER TABLE mandate
+ADD COLUMN IF NOT EXISTS merchant_connector_id VARCHAR(32);
diff --git a/migrations/2023-10-23-101023_add_organization_table/down.sql b/migrations/2023-10-23-101023_add_organization_table/down.sql
new file mode 100644
index 000000000000..9f267438f537
--- /dev/null
+++ b/migrations/2023-10-23-101023_add_organization_table/down.sql
@@ -0,0 +1,2 @@
+-- This file should undo anything in `up.sql`
+DROP TABLE IF EXISTS ORGANIZATION;
diff --git a/migrations/2023-10-23-101023_add_organization_table/up.sql b/migrations/2023-10-23-101023_add_organization_table/up.sql
new file mode 100644
index 000000000000..6e8cf3cf5424
--- /dev/null
+++ b/migrations/2023-10-23-101023_add_organization_table/up.sql
@@ -0,0 +1,5 @@
+-- Your SQL goes here
+CREATE TABLE IF NOT EXISTS ORGANIZATION (
+    org_id VARCHAR(32) PRIMARY KEY NOT NULL,
+    org_name TEXT
+);
diff --git a/migrations/2023-10-25-070909_add_merchant_custom_name_payment_link/down.sql b/migrations/2023-10-25-070909_add_merchant_custom_name_payment_link/down.sql
new file mode 100644
index 000000000000..84f009021df8
--- /dev/null
+++ b/migrations/2023-10-25-070909_add_merchant_custom_name_payment_link/down.sql
@@ -0,0 +1,2 @@
+-- This file should undo anything in `up.sql`
+ALTER TABLE payment_link DROP COLUMN custom_merchant_name;
diff --git a/migrations/2023-10-25-070909_add_merchant_custom_name_payment_link/up.sql b/migrations/2023-10-25-070909_add_merchant_custom_name_payment_link/up.sql
new file mode 100644
index 000000000000..c4fa756e57a0
--- /dev/null
+++ b/migrations/2023-10-25-070909_add_merchant_custom_name_payment_link/up.sql
@@ -0,0 +1,2 @@
+-- Your SQL goes here
+ALTER TABLE payment_link ADD COLUMN custom_merchant_name VARCHAR(64);
\ No newline at end of file
diff --git a/migrations/2023-11-02-074243_make_customer_id_nullable_in_address_table/down.sql b/migrations/2023-11-02-074243_make_customer_id_nullable_in_address_table/down.sql
new file mode 100644
index 000000000000..b148e66d8750
--- /dev/null
+++ b/migrations/2023-11-02-074243_make_customer_id_nullable_in_address_table/down.sql
@@ -0,0 +1,2 @@
+-- This file should undo anything in `up.sql`
+ALTER TABLE address ALTER COLUMN customer_id SET NOT NULL;
\ No newline at end of file
diff --git a/migrations/2023-11-02-074243_make_customer_id_nullable_in_address_table/up.sql b/migrations/2023-11-02-074243_make_customer_id_nullable_in_address_table/up.sql
new file mode 100644
index 000000000000..98826c41e79c
--- /dev/null
+++ b/migrations/2023-11-02-074243_make_customer_id_nullable_in_address_table/up.sql
@@ -0,0 +1,2 @@
+-- Your SQL goes here
+ALTER TABLE address ALTER COLUMN customer_id DROP NOT NULL;
\ No newline at end of file
diff --git a/migrations/2023-11-06-110233_create_user_table/down.sql b/migrations/2023-11-06-110233_create_user_table/down.sql
new file mode 100644
index 000000000000..0172a87499bb
--- /dev/null
+++ b/migrations/2023-11-06-110233_create_user_table/down.sql
@@ -0,0 +1,2 @@
+-- This file should undo anything in `up.sql`
+DROP TABLE users;
\ No newline at end of file
diff --git a/migrations/2023-11-06-110233_create_user_table/up.sql b/migrations/2023-11-06-110233_create_user_table/up.sql
new file mode 100644
index 000000000000..410436c461ce
--- /dev/null
+++ b/migrations/2023-11-06-110233_create_user_table/up.sql
@@ -0,0 +1,14 @@
+-- Your SQL goes here
+CREATE TABLE IF NOT EXISTS users (
+    id SERIAL PRIMARY KEY,
+    user_id VARCHAR(64) NOT NULL UNIQUE,
+    email VARCHAR(255) NOT NULL UNIQUE,
+    name VARCHAR(255) NOT NULL,
+    password VARCHAR(255) NOT NULL,
+    is_verified bool NOT NULL DEFAULT false,
+    created_at TIMESTAMP NOT NULL DEFAULT now(),
+    last_modified_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE UNIQUE INDEX IF NOT EXISTS user_id_index ON users (user_id);
+CREATE UNIQUE INDEX IF NOT EXISTS user_email_index ON users (email);
\ No newline at end of file
diff --git a/migrations/2023-11-06-113726_create_user_roles_table/down.sql b/migrations/2023-11-06-113726_create_user_roles_table/down.sql
new file mode 100644
index 000000000000..5e6350de9e70
--- /dev/null
+++ b/migrations/2023-11-06-113726_create_user_roles_table/down.sql
@@ -0,0 +1,4 @@
+-- This file should undo anything in `up.sql`
+
+-- Drop the table
+DROP TABLE IF EXISTS user_roles;
\ No newline at end of file
diff --git a/migrations/2023-11-06-113726_create_user_roles_table/up.sql b/migrations/2023-11-06-113726_create_user_roles_table/up.sql
new file mode 100644
index 000000000000..768306721626
--- /dev/null
+++ b/migrations/2023-11-06-113726_create_user_roles_table/up.sql
@@ -0,0 +1,18 @@
+-- Your SQL goes here
+CREATE TABLE IF NOT EXISTS user_roles (
+	id SERIAL PRIMARY KEY,
+	user_id VARCHAR(64) NOT NULL,
+	merchant_id VARCHAR(64) NOT NULL,
+	role_id VARCHAR(64) NOT NULL,
+	org_id VARCHAR(64) NOT NULL, 
+	status VARCHAR(64) NOT NULL, 
+	created_by VARCHAR(64) NOT NULL,
+	last_modified_by VARCHAR(64) NOT NULL,
+	created_at TIMESTAMP NOT NULL DEFAULT now(),
+	last_modified_at TIMESTAMP NOT NULL DEFAULT now(),
+	CONSTRAINT user_merchant_unique UNIQUE (user_id, merchant_id)
+);
+
+
+CREATE INDEX IF NOT EXISTS  user_id_roles_index ON user_roles (user_id);
+CREATE INDEX IF NOT EXISTS  user_mid_roles_index ON user_roles (merchant_id);
\ No newline at end of file
diff --git a/migrations/2023-11-07-110139_add_gsm_table/down.sql b/migrations/2023-11-07-110139_add_gsm_table/down.sql
new file mode 100644
index 000000000000..e1cdd5d4133d
--- /dev/null
+++ b/migrations/2023-11-07-110139_add_gsm_table/down.sql
@@ -0,0 +1,2 @@
+-- Tables
+DROP TABLE gateway_status_map;
diff --git a/migrations/2023-11-07-110139_add_gsm_table/up.sql b/migrations/2023-11-07-110139_add_gsm_table/up.sql
new file mode 100644
index 000000000000..9dfa68b01af9
--- /dev/null
+++ b/migrations/2023-11-07-110139_add_gsm_table/up.sql
@@ -0,0 +1,16 @@
+-- Your SQL goes here
+-- Tables
+CREATE TABLE IF NOT EXISTS gateway_status_map (
+    connector VARCHAR(64) NOT NULL,
+    flow VARCHAR(64) NOT NULL,
+    sub_flow VARCHAR(64) NOT NULL,
+    code VARCHAR(255) NOT NULL,
+    message VARCHAR(1024),
+    status VARCHAR(64) NOT NULL,
+    router_error VARCHAR(64),
+    decision VARCHAR(64) NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP,
+    last_modified TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP,
+    step_up_possible BOOLEAN NOT NULL DEFAULT FALSE,
+    PRIMARY KEY (connector, flow, sub_flow, code, message)
+);
diff --git a/migrations/2023-11-08-144951_drop_connector_response_table/down.sql b/migrations/2023-11-08-144951_drop_connector_response_table/down.sql
new file mode 100644
index 000000000000..ff9ca4e4f9c7
--- /dev/null
+++ b/migrations/2023-11-08-144951_drop_connector_response_table/down.sql
@@ -0,0 +1,34 @@
+-- This file should undo anything in `up.sql`
+CREATE TABLE connector_response (
+    id SERIAL PRIMARY KEY,
+    payment_id VARCHAR(255) NOT NULL,
+    merchant_id VARCHAR(255) NOT NULL,
+    txn_id VARCHAR(255) NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP,
+    modified_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP,
+    connector_name VARCHAR(32) NOT NULL,
+    connector_transaction_id VARCHAR(255),
+    authentication_data JSON,
+    encoded_data TEXT
+);
+
+CREATE UNIQUE INDEX connector_response_id_index ON connector_response (payment_id, merchant_id, txn_id);
+
+ALTER TABLE connector_response ALTER COLUMN connector_name DROP NOT NULL;
+ALTER TABLE connector_response RENAME COLUMN txn_id TO attempt_id;
+ALTER TABLE connector_response
+    ALTER COLUMN payment_id TYPE VARCHAR(64),
+    ALTER COLUMN merchant_id TYPE VARCHAR(64),
+    ALTER COLUMN attempt_id TYPE VARCHAR(64),
+    ALTER COLUMN connector_name TYPE VARCHAR(64),
+    ALTER COLUMN connector_transaction_id TYPE VARCHAR(128);
+
+
+
+ALTER TABLE connector_response
+ALTER COLUMN modified_at DROP DEFAULT;
+
+ALTER TABLE connector_response
+ALTER COLUMN created_at DROP DEFAULT;
+
+ALTER TABLE connector_response ADD column updated_by VARCHAR(32) NOT NULL DEFAULT 'postgres_only';
diff --git a/migrations/2023-11-08-144951_drop_connector_response_table/up.sql b/migrations/2023-11-08-144951_drop_connector_response_table/up.sql
new file mode 100644
index 000000000000..0059a6b38dc1
--- /dev/null
+++ b/migrations/2023-11-08-144951_drop_connector_response_table/up.sql
@@ -0,0 +1,2 @@
+-- Your SQL goes here
+DROP TABLE connector_response; --NOT to run in deployment envs
\ No newline at end of file
diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json
index 041ddf57ff04..688c324a25ff 100644
--- a/openapi/openapi_spec.json
+++ b/openapi/openapi_spec.json
@@ -1063,32 +1063,6 @@
             "application/json": {
               "schema": {
                 "$ref": "#/components/schemas/PaymentsCreateRequest"
-              },
-              "examples": {
-                "Create a 3DS payment": {
-                  "value": "{\n        \"amount\": 6540,\n        \"currency\": \"USD\",\n        \"authentication_type\" : \"three_ds\"\n    }"
-                },
-                "Create a manual capture payment": {
-                  "value": "{\n        \"amount\": 6540,\n        \"currency\": \"USD\",\n        \"capture_method\":\"manual\"\n    }"
-                },
-                "Create a payment": {
-                  "value": "{\n        \"amount\": 6540,\n        \"currency\": \"USD\",\n        \"payment_id\": \"abcdefghijklmnopqrstuvwxyz\",\n        \"customer\": {\n            \"id\":\"cus_abcdefgh\",\n            \"name\":\"John Dough\",\n            \"phone\":\"9999999999\",\n            \"email\":\"john@example.com\"\n        },\n        \"description\": \"Its my first payment request\",\n        \"statement_descriptor_name\": \"joseph\",\n        \"statement_descriptor_suffix\": \"JS\",\n        \"metadata\": {\n            \"udf1\": \"some-value\",\n            \"udf2\": \"some-value\"\n        }\n    }"
-                },
-                "Create a payment with address": {
-                  "value": "{\n        \"amount\": 6540,\n        \"currency\": \"USD\",\n        \"customer\": {\n            \"id\" : \"cus_abcdefgh\"\n        },\n        \"billing\": {\n            \"address\": {\n                \"line1\": \"1467\",\n                \"line2\": \"Harrison Street\",\n                \"line3\": \"Harrison Street\",\n                \"city\": \"San Fransico\",\n                \"state\": \"California\",\n                \"zip\": \"94122\",\n                \"country\": \"US\",\n                \"first_name\": \"joseph\",\n                \"last_name\": \"Doe\"\n            },\n            \"phone\": {\n                \"number\": \"8056594427\",\n                \"country_code\": \"+91\"\n            }\n        }\n    }"
-                },
-                "Create a payment with customer details": {
-                  "value": "{\n        \"amount\": 6540,\n        \"currency\": \"USD\",\n        \"customer\": {\n            \"id\":\"cus_abcdefgh\",\n            \"name\":\"John Dough\",\n            \"phone\":\"9999999999\",\n            \"email\":\"john@example.com\"\n        }\n    }"
-                },
-                "Create a payment with minimul fields": {
-                  "value": "{\n        \"amount\": 6540,\n        \"currency\": \"USD\",\n    }"
-                },
-                "Create a payment with order category for noon": {
-                  "value": "{\n        \"amount\": 6540,\n        \"currency\": \"USD\",\n        \"connector_metadata\": {\n            \"noon\": {\n                \"order_category\":\"shoes\"\n            }\n        }\n    }"
-                },
-                "Create a payment with order details": {
-                  "value": "{\n        \"amount\": 6540,\n        \"currency\": \"USD\",\n        \"order_details\": [\n            {\n                \"product_name\": \"Apple iPhone 15\",\n                \"quantity\": 1,\n                \"amount\" : 6540\n            }\n        ]\n    }"
-                }
               }
             }
           },
@@ -3935,8 +3909,8 @@
           "adyen",
           "airwallex",
           "authorizedotnet",
-          "bitpay",
           "bambora",
+          "bitpay",
           "bluesnap",
           "boku",
           "braintree",
@@ -3973,6 +3947,7 @@
           "stripe",
           "trustpay",
           "tsys",
+          "volt",
           "wise",
           "worldline",
           "worldpay",
@@ -7846,15 +7821,11 @@
       "PaymentLinkColorSchema": {
         "type": "object",
         "properties": {
-          "primary_color": {
+          "background_primary_color": {
             "type": "string",
             "nullable": true
           },
-          "primary_accent_color": {
-            "type": "string",
-            "nullable": true
-          },
-          "secondary_color": {
+          "sdk_theme": {
             "type": "string",
             "nullable": true
           }
@@ -7903,6 +7874,11 @@
           "merchant_custom_domain_name": {
             "type": "string",
             "nullable": true
+          },
+          "custom_merchant_name": {
+            "type": "string",
+            "description": "Custom merchant name for payment link",
+            "nullable": true
           }
         }
       },
@@ -9785,6 +9761,11 @@
             "type": "string",
             "description": "Denotes the action(approve or reject) taken by merchant in case of manual review. Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment",
             "nullable": true
+          },
+          "merchant_connector_id": {
+            "type": "string",
+            "description": "Identifier of the connector ( merchant connector account ) which was chosen to make the payment",
+            "nullable": true
           }
         }
       },
@@ -10719,6 +10700,10 @@
             "type": "string",
             "description": "The connector used for the refund and the corresponding payment",
             "example": "stripe"
+          },
+          "profile_id": {
+            "type": "string",
+            "nullable": true
           }
         }
       },
@@ -11247,12 +11232,12 @@
           "start_time": {
             "type": "string",
             "format": "date-time",
-            "description": "The start time to filter refunds list or to get list of filters. To get list of filters start time is needed to be passed"
+            "description": "The start time to filter payments list or to get list of filters. To get list of filters start time is needed to be passed"
           },
           "end_time": {
             "type": "string",
             "format": "date-time",
-            "description": "The end time to filter refunds list or to get list of filters. If not passed the default time is now",
+            "description": "The end time to filter payments list or to get list of filters. If not passed the default time is now",
             "nullable": true
           }
         }
diff --git a/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/.meta.json b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/.meta.json
new file mode 100644
index 000000000000..69b505c6d863
--- /dev/null
+++ b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/.meta.json	
@@ -0,0 +1,3 @@
+{
+  "childrenOrder": ["Payments - Create", "Payments - Retrieve"]
+}
diff --git a/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Create/.event.meta.json b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Create/.event.meta.json
new file mode 100644
index 000000000000..0731450e6b25
--- /dev/null
+++ b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Create/.event.meta.json	
@@ -0,0 +1,3 @@
+{
+  "eventOrder": ["event.test.js"]
+}
diff --git a/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Create/event.test.js b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Create/event.test.js
new file mode 100644
index 000000000000..bd103ebf78b4
--- /dev/null
+++ b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Create/event.test.js	
@@ -0,0 +1,71 @@
+// Validate status 2xx
+pm.test("[POST]::/payments - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[POST]::/payments - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[POST]::/payments - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "processing" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments - Content check if value for 'status' matches 'succeeded'",
+    function () {
+      pm.expect(jsonData.status).to.eql("succeeded");
+    },
+  );
+}
diff --git a/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Create/request.json b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Create/request.json
new file mode 100644
index 000000000000..0bf23604d848
--- /dev/null
+++ b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Create/request.json	
@@ -0,0 +1,89 @@
+{
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "amount": 0,
+      "currency": "USD",
+      "confirm": true,
+      "capture_method": "automatic",
+      "capture_on": "2022-09-10T10:11:12Z",
+      "customer_id": "StripeCustomer",
+      "email": "guest@example.com",
+      "name": "John Doe",
+      "phone": "999999999",
+      "phone_country_code": "+65",
+      "description": "Its my first payment request",
+      "authentication_type": "no_three_ds",
+      "routing": {
+        "type": "single",
+        "data": "forte"
+      },
+      "return_url": "https://duck.com",
+      "payment_method": "card",
+      "payment_method_data": {
+        "card": {
+          "card_number": "4242424242424242",
+          "card_exp_month": "10",
+          "card_exp_year": "25",
+          "card_holder_name": "joseph Doe",
+          "card_cvc": "123"
+        }
+      },
+      "billing": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "PiX",
+          "last_name": "Fix"
+        }
+      },
+      "shipping": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "PiX",
+          "last_name": "Fix"
+        }
+      },
+      "statement_descriptor_name": "joseph",
+      "statement_descriptor_suffix": "JS",
+      "metadata": {
+        "udf1": "value1",
+        "new_customer": "true",
+        "login_date": "2019-09-10T10:11:12Z"
+      }
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/payments",
+    "host": ["{{baseUrl}}"],
+    "path": ["payments"]
+  },
+  "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+}
diff --git a/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Create/response.json b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Create/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Create/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Retrieve/.event.meta.json b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Retrieve/.event.meta.json
new file mode 100644
index 000000000000..0731450e6b25
--- /dev/null
+++ b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Retrieve/.event.meta.json	
@@ -0,0 +1,3 @@
+{
+  "eventOrder": ["event.test.js"]
+}
diff --git a/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Retrieve/event.test.js b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Retrieve/event.test.js
new file mode 100644
index 000000000000..16efd2245bec
--- /dev/null
+++ b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Retrieve/event.test.js	
@@ -0,0 +1,71 @@
+// Validate status 2xx
+pm.test("[GET]::/payments/:id - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[GET]::/payments/:id - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[GET]::/payments/:id - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "processing" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments/:id - Content check if value for 'status' matches 'succeeded'",
+    function () {
+      pm.expect(jsonData.status).to.eql("succeeded");
+    },
+  );
+}
diff --git a/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Retrieve/request.json b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Retrieve/request.json
new file mode 100644
index 000000000000..6cd4b7d96c52
--- /dev/null
+++ b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Retrieve/request.json	
@@ -0,0 +1,28 @@
+{
+  "method": "GET",
+  "header": [
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "url": {
+    "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+    "host": ["{{baseUrl}}"],
+    "path": ["payments", ":id"],
+    "query": [
+      {
+        "key": "force_sync",
+        "value": "true"
+      }
+    ],
+    "variable": [
+      {
+        "key": "id",
+        "value": "{{payment_id}}",
+        "description": "(Required) unique payment id"
+      }
+    ]
+  },
+  "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+}
diff --git a/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Retrieve/response.json b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Retrieve/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/forte/Flow Testcases/Happy Cases/Scenario7-Create payment with Zero Amount/Payments - Retrieve/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/forte/Flow Testcases/QuickStart/Payments - Create/request.json b/postman/collection-dir/forte/Flow Testcases/QuickStart/Payments - Create/request.json
index 05fde18c2d97..04be684704b6 100644
--- a/postman/collection-dir/forte/Flow Testcases/QuickStart/Payments - Create/request.json	
+++ b/postman/collection-dir/forte/Flow Testcases/QuickStart/Payments - Create/request.json	
@@ -21,6 +21,10 @@
       "amount": 6540,
       "currency": "USD",
       "confirm": true,
+      "routing": {
+        "type": "single",
+        "data": "forte"
+      },
       "capture_method": "automatic",
       "capture_on": "2022-09-10T10:11:12Z",
       "amount_to_capture": 6540,
diff --git a/postman/collection-dir/multisafepay/Flow Testcases/QuickStart/Payments - Create/request.json b/postman/collection-dir/multisafepay/Flow Testcases/QuickStart/Payments - Create/request.json
index 289e780a72cb..a4e816ad17d2 100644
--- a/postman/collection-dir/multisafepay/Flow Testcases/QuickStart/Payments - Create/request.json	
+++ b/postman/collection-dir/multisafepay/Flow Testcases/QuickStart/Payments - Create/request.json	
@@ -55,6 +55,10 @@
           "last_name": "happy"
         }
       },
+      "routing": {
+        "type": "single",
+        "data": "multisafepay"
+      },
       "shipping": {
         "address": {
           "line1": "1467",
diff --git a/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payment Connector - Update/.event.meta.json b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payment Connector - Update/.event.meta.json
new file mode 100644
index 000000000000..0731450e6b25
--- /dev/null
+++ b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payment Connector - Update/.event.meta.json	
@@ -0,0 +1,3 @@
+{
+  "eventOrder": ["event.test.js"]
+}
diff --git a/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payment Connector - Update/event.test.js b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payment Connector - Update/event.test.js
new file mode 100644
index 000000000000..d7259b6a840b
--- /dev/null
+++ b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payment Connector - Update/event.test.js	
@@ -0,0 +1,39 @@
+// Validate status 2xx
+pm.test(
+  "[POST]::/account/:account_id/connectors/:connector_id - Status code is 2xx",
+  function () {
+    pm.response.to.be.success;
+  },
+);
+
+// Validate if response header has matching content-type
+pm.test(
+  "[POST]::/account/:account_id/connectors/:connector_id - Content-Type is application/json",
+  function () {
+    pm.expect(pm.response.headers.get("Content-Type")).to.include(
+      "application/json",
+    );
+  },
+);
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set merchant_connector_id as variable for jsonData.merchant_connector_id
+if (jsonData?.merchant_connector_id) {
+  pm.collectionVariables.set(
+    "merchant_connector_id",
+    jsonData.merchant_connector_id,
+  );
+  console.log(
+    "- use {{merchant_connector_id}} as collection variable for value",
+    jsonData.merchant_connector_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{merchant_connector_id}}, as jsonData.merchant_connector_id is undefined.",
+  );
+}
diff --git a/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payment Connector - Update/request.json b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payment Connector - Update/request.json
new file mode 100644
index 000000000000..5328f86fbc92
--- /dev/null
+++ b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payment Connector - Update/request.json	
@@ -0,0 +1,122 @@
+{
+  "auth": {
+    "type": "apikey",
+    "apikey": [
+      {
+        "key": "value",
+        "value": "{{admin_api_key}}",
+        "type": "string"
+      },
+      {
+        "key": "key",
+        "value": "api-key",
+        "type": "string"
+      },
+      {
+        "key": "in",
+        "value": "header",
+        "type": "string"
+      }
+    ]
+  },
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "connector_type": "fiz_operations",
+      "connector_account_details": {
+        "auth_type": "HeaderKey",
+        "api_key": "wrongAPIKey"
+      },
+      "test_mode": false,
+      "disabled": false,
+      "payment_methods_enabled": [
+        {
+          "payment_method": "card",
+          "payment_method_types": [
+            {
+              "payment_method_type": "credit",
+              "card_networks": ["Visa", "Mastercard"],
+              "minimum_amount": 1,
+              "maximum_amount": 68607706,
+              "recurring_enabled": true,
+              "installment_payment_enabled": true
+            },
+            {
+              "payment_method_type": "debit",
+              "card_networks": ["Visa", "Mastercard"],
+              "minimum_amount": 1,
+              "maximum_amount": 68607706,
+              "recurring_enabled": true,
+              "installment_payment_enabled": true
+            }
+          ]
+        },
+        {
+          "payment_method": "pay_later",
+          "payment_method_types": [
+            {
+              "payment_method_type": "klarna",
+              "payment_experience": "redirect_to_url",
+              "minimum_amount": 1,
+              "maximum_amount": 68607706,
+              "recurring_enabled": true,
+              "installment_payment_enabled": true
+            },
+            {
+              "payment_method_type": "affirm",
+              "payment_experience": "redirect_to_url",
+              "minimum_amount": 1,
+              "maximum_amount": 68607706,
+              "recurring_enabled": true,
+              "installment_payment_enabled": true
+            },
+            {
+              "payment_method_type": "afterpay_clearpay",
+              "payment_experience": "redirect_to_url",
+              "minimum_amount": 1,
+              "maximum_amount": 68607706,
+              "recurring_enabled": true,
+              "installment_payment_enabled": true
+            }
+          ]
+        }
+      ],
+      "metadata": {
+        "city": "NY",
+        "unit": "245"
+      }
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/account/:account_id/connectors/:connector_id",
+    "host": ["{{baseUrl}}"],
+    "path": ["account", ":account_id", "connectors", ":connector_id"],
+    "variable": [
+      {
+        "key": "account_id",
+        "value": "{{merchant_id}}"
+      },
+      {
+        "key": "connector_id",
+        "value": "{{merchant_connector_id}}"
+      }
+    ]
+  },
+  "description": "To update an existing Payment Connector. Helpful in enabling / disabling different payment methods and other settings for the connector etc"
+}
diff --git a/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payment Connector - Update/response.json b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payment Connector - Update/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payment Connector - Update/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payments - Create/.event.meta.json b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payments - Create/.event.meta.json
new file mode 100644
index 000000000000..0731450e6b25
--- /dev/null
+++ b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payments - Create/.event.meta.json	
@@ -0,0 +1,3 @@
+{
+  "eventOrder": ["event.test.js"]
+}
diff --git a/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payments - Create/event.test.js b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payments - Create/event.test.js
new file mode 100644
index 000000000000..e75cb69a9249
--- /dev/null
+++ b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payments - Create/event.test.js	
@@ -0,0 +1,56 @@
+// Validate status 2xx
+pm.test("[POST]::/payments - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[POST]::/payments - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[POST]::/payments - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// Validate error message in the JSON Body
+pm.test("[POST]::/payments - Validate error message", function () {
+  pm.expect(jsonData.error_message).to.not.be.null
+});
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
diff --git a/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payments - Create/request.json b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payments - Create/request.json
new file mode 100644
index 000000000000..525eaa739e83
--- /dev/null
+++ b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payments - Create/request.json	
@@ -0,0 +1,90 @@
+{
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "amount": 6540,
+      "currency": "USD",
+      "confirm": true,
+      "capture_method": "automatic",
+      "capture_on": "2022-09-10T10:11:12Z",
+      "amount_to_capture": 6540,
+      "customer_id": "StripeCustomer",
+      "email": "guest@example.com",
+      "name": "John Doe",
+      "phone": "999999999",
+      "phone_country_code": "+1",
+      "description": "Its my first payment request",
+      "authentication_type": "no_three_ds",
+      "return_url": "https://duck.com",
+      "payment_method": "card",
+      "payment_method_data": {
+        "card": {
+          "card_number": "4242424242424242",
+          "card_exp_month": "10",
+          "card_exp_year": "25",
+          "card_holder_name": "joseph Doe",
+          "card_cvc": "123"
+        }
+      },
+      "routing": {
+        "type": "single",
+        "data": "multisafepay"
+      },
+      "billing": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "someone",
+          "last_name": "happy"
+        }
+      },
+      "shipping": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "someone",
+          "last_name": "happy"
+        }
+      },
+      "statement_descriptor_name": "joseph",
+      "statement_descriptor_suffix": "JS",
+      "metadata": {
+        "udf1": "value1",
+        "new_customer": "true",
+        "login_date": "2019-09-10T10:11:12Z"
+      }
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/payments",
+    "host": ["{{baseUrl}}"],
+    "path": ["payments"]
+  },
+  "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+}
diff --git a/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payments - Create/response.json b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payments - Create/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/multisafepay/Flow Testcases/Variation Cases/Scenario6- Create payment with Invalid Merchant ID/Payments - Create/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/request.json b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/request.json
index 144a35f773aa..09772bd13de5 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/request.json	
@@ -34,7 +34,7 @@
       "payment_method": "card",
       "payment_method_data": {
         "card": {
-          "card_number": "4005519200000004",
+          "card_number": "4012000033330026",
           "card_exp_month": "10",
           "card_exp_year": "25",
           "card_holder_name": "joseph Doe",
diff --git a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario11-Create Partial Capture payment/Payments - Create/request.json b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario11-Create Partial Capture payment/Payments - Create/request.json
index 5b606850fd2e..c3b86fd9b2d3 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario11-Create Partial Capture payment/Payments - Create/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario11-Create Partial Capture payment/Payments - Create/request.json	
@@ -34,7 +34,7 @@
       "payment_method": "card",
       "payment_method_data": {
         "card": {
-          "card_number": "4005519200000004",
+          "card_number": "4012000033330026",
           "card_exp_month": "10",
           "card_exp_year": "25",
           "card_holder_name": "joseph Doe",
diff --git a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/request.json b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/request.json
index a6a8150c2404..8fca41333799 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/request.json	
@@ -34,7 +34,7 @@
       "payment_method": "card",
       "payment_method_data": {
         "card": {
-          "card_number": "4005519200000004",
+          "card_number": "4012000033330026",
           "card_exp_month": "10",
           "card_exp_year": "25",
           "card_holder_name": "joseph Doe",
diff --git a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/request.json b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/request.json
index b9e2faa143c9..be7b29473334 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/request.json	
@@ -42,7 +42,7 @@
       "payment_method": "card",
       "payment_method_data": {
         "card": {
-          "card_number": "4005519200000004",
+          "card_number": "4012000033330026",
           "card_exp_month": "10",
           "card_exp_year": "25",
           "card_holder_name": "joseph Doe",
diff --git a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture with confirm false/Payments - Create/request.json b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture with confirm false/Payments - Create/request.json
index 50cb0663b403..b9b658979cf2 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture with confirm false/Payments - Create/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture with confirm false/Payments - Create/request.json	
@@ -34,7 +34,7 @@
       "payment_method": "card",
       "payment_method_data": {
         "card": {
-          "card_number": "4005519200000004",
+          "card_number": "4012000033330026",
           "card_exp_month": "10",
           "card_exp_year": "25",
           "card_holder_name": "joseph Doe",
diff --git a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture/Payments - Create/request.json b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture/Payments - Create/request.json
index 5b606850fd2e..c3b86fd9b2d3 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture/Payments - Create/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario4-Create payment with Manual capture/Payments - Create/request.json	
@@ -34,7 +34,7 @@
       "payment_method": "card",
       "payment_method_data": {
         "card": {
-          "card_number": "4005519200000004",
+          "card_number": "4012000033330026",
           "card_exp_month": "10",
           "card_exp_year": "25",
           "card_holder_name": "joseph Doe",
diff --git a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario5-Void the payment/Payments - Create/request.json b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario5-Void the payment/Payments - Create/request.json
index 5b606850fd2e..c3b86fd9b2d3 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario5-Void the payment/Payments - Create/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario5-Void the payment/Payments - Create/request.json	
@@ -34,7 +34,7 @@
       "payment_method": "card",
       "payment_method_data": {
         "card": {
-          "card_number": "4005519200000004",
+          "card_number": "4012000033330026",
           "card_exp_month": "10",
           "card_exp_year": "25",
           "card_holder_name": "joseph Doe",
diff --git a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario8-Create payment with Manual capture with confirm false and surcharge_data/Payments - Confirm/request.json b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario8-Create payment with Manual capture with confirm false and surcharge_data/Payments - Confirm/request.json
index c60989439784..8559af25e82c 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario8-Create payment with Manual capture with confirm false and surcharge_data/Payments - Confirm/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario8-Create payment with Manual capture with confirm false and surcharge_data/Payments - Confirm/request.json	
@@ -42,6 +42,16 @@
       "surcharge_details": {
         "surcharge_amount": 5,
         "tax_amount": 5
+      },
+      "payment_method": "card",
+      "payment_method_data": {
+        "card": {
+          "card_number": "4012000033330026",
+          "card_exp_month": "10",
+          "card_exp_year": "25",
+          "card_holder_name": "joseph Doe",
+          "card_cvc": "123"
+        }
       }
     }
   },
diff --git a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario8-Create payment with Manual capture with confirm false and surcharge_data/Payments - Create/event.test.js b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario8-Create payment with Manual capture with confirm false and surcharge_data/Payments - Create/event.test.js
index fe83ca7852a5..b6d04374f6b3 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario8-Create payment with Manual capture with confirm false and surcharge_data/Payments - Create/event.test.js	
+++ b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario8-Create payment with Manual capture with confirm false and surcharge_data/Payments - Create/event.test.js	
@@ -63,9 +63,9 @@ if (jsonData?.client_secret) {
 // Response body should have value "requires_confirmation" for "status"
 if (jsonData?.status) {
   pm.test(
-    "[POST]::/payments - Content check if value for 'status' matches 'requires_capture'",
+    "[POST]::/payments - Content check if value for 'status' matches 'requires_payment_method'",
     function () {
-      pm.expect(jsonData.status).to.eql("requires_confirmation");
+      pm.expect(jsonData.status).to.eql("requires_payment_method");
     },
   );
 }
diff --git a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario8-Create payment with Manual capture with confirm false and surcharge_data/Payments - Create/request.json b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario8-Create payment with Manual capture with confirm false and surcharge_data/Payments - Create/request.json
index b080ff1a6b95..f7d813c34efd 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario8-Create payment with Manual capture with confirm false and surcharge_data/Payments - Create/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Happy Cases/Scenario8-Create payment with Manual capture with confirm false and surcharge_data/Payments - Create/request.json	
@@ -31,16 +31,6 @@
       "description": "Its my first payment request",
       "authentication_type": "no_three_ds",
       "return_url": "https://duck.com",
-      "payment_method": "card",
-      "payment_method_data": {
-        "card": {
-          "card_number": "4005519200000004",
-          "card_exp_month": "10",
-          "card_exp_year": "25",
-          "card_holder_name": "joseph Doe",
-          "card_cvc": "123"
-        }
-      },
       "billing": {
         "address": {
           "line1": "1467",
diff --git a/postman/collection-dir/paypal/Flow Testcases/QuickStart/Merchant Account - Create/request.json b/postman/collection-dir/paypal/Flow Testcases/QuickStart/Merchant Account - Create/request.json
index 5aa155f64c37..7df5315150cd 100644
--- a/postman/collection-dir/paypal/Flow Testcases/QuickStart/Merchant Account - Create/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/QuickStart/Merchant Account - Create/request.json	
@@ -79,10 +79,6 @@
       "metadata": {
         "city": "NY",
         "unit": "245"
-      },
-      "routing_algorithm": {
-        "type": "single",
-        "data": "paypal"
       }
     }
   },
diff --git a/postman/collection-dir/paypal/Flow Testcases/QuickStart/Payments - Create/request.json b/postman/collection-dir/paypal/Flow Testcases/QuickStart/Payments - Create/request.json
index 07ffc4eedefc..d54ac18d3c50 100644
--- a/postman/collection-dir/paypal/Flow Testcases/QuickStart/Payments - Create/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/QuickStart/Payments - Create/request.json	
@@ -35,7 +35,7 @@
       "payment_method": "card",
       "payment_method_data": {
         "card": {
-          "card_number": "4005519200000004",
+          "card_number": "4012000033330026",
           "card_exp_month": "10",
           "card_exp_year": "25",
           "card_holder_name": "joseph Doe",
diff --git a/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario1-Create payment with Invalid card details/Payments - Create(Invalid Exp month)/request.json b/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario1-Create payment with Invalid card details/Payments - Create(Invalid Exp month)/request.json
index 6e9db26a339d..ad8aa7b2ae06 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario1-Create payment with Invalid card details/Payments - Create(Invalid Exp month)/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario1-Create payment with Invalid card details/Payments - Create(Invalid Exp month)/request.json	
@@ -35,7 +35,7 @@
       "payment_method": "card",
       "payment_method_data": {
         "card": {
-          "card_number": "4005519200000004",
+          "card_number": "4012000033330026",
           "card_exp_month": "13",
           "card_exp_year": "2023",
           "card_holder_name": "joseph Doe",
diff --git a/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario1-Create payment with Invalid card details/Payments - Create(invalid CVV)/request.json b/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario1-Create payment with Invalid card details/Payments - Create(invalid CVV)/request.json
index 0b35b7a4e92b..ab5943ac13ac 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario1-Create payment with Invalid card details/Payments - Create(invalid CVV)/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario1-Create payment with Invalid card details/Payments - Create(invalid CVV)/request.json	
@@ -35,7 +35,7 @@
       "payment_method": "card",
       "payment_method_data": {
         "card": {
-          "card_number": "4005519200000004",
+          "card_number": "4012000033330026",
           "card_exp_month": "10",
           "card_exp_year": "25",
           "card_holder_name": "joseph Doe",
diff --git a/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario3-Capture greater amount/Payments - Create/request.json b/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario3-Capture greater amount/Payments - Create/request.json
index 5b606850fd2e..c3b86fd9b2d3 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario3-Capture greater amount/Payments - Create/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario3-Capture greater amount/Payments - Create/request.json	
@@ -34,7 +34,7 @@
       "payment_method": "card",
       "payment_method_data": {
         "card": {
-          "card_number": "4005519200000004",
+          "card_number": "4012000033330026",
           "card_exp_month": "10",
           "card_exp_year": "25",
           "card_holder_name": "joseph Doe",
diff --git a/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario4-Capture the succeeded payment/Payments - Create/request.json b/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario4-Capture the succeeded payment/Payments - Create/request.json
index 144a35f773aa..09772bd13de5 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario4-Capture the succeeded payment/Payments - Create/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario4-Capture the succeeded payment/Payments - Create/request.json	
@@ -34,7 +34,7 @@
       "payment_method": "card",
       "payment_method_data": {
         "card": {
-          "card_number": "4005519200000004",
+          "card_number": "4012000033330026",
           "card_exp_month": "10",
           "card_exp_year": "25",
           "card_holder_name": "joseph Doe",
diff --git a/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario5-Void the success_slash_failure payment/Payments - Create/request.json b/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario5-Void the success_slash_failure payment/Payments - Create/request.json
index 09987daa71ec..d7582d82ddea 100644
--- a/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario5-Void the success_slash_failure payment/Payments - Create/request.json	
+++ b/postman/collection-dir/paypal/Flow Testcases/Variation Cases/Scenario5-Void the success_slash_failure payment/Payments - Create/request.json	
@@ -35,7 +35,7 @@
       "payment_method": "card",
       "payment_method_data": {
         "card": {
-          "card_number": "4005519200000004",
+          "card_number": "4012000033330026",
           "card_exp_month": "10",
           "card_exp_year": "25",
           "card_holder_name": "joseph Doe",
diff --git a/postman/collection-dir/paypal/event.prerequest.js b/postman/collection-dir/paypal/event.prerequest.js
index e69de29bb2d1..f4c9a7648646 100644
--- a/postman/collection-dir/paypal/event.prerequest.js
+++ b/postman/collection-dir/paypal/event.prerequest.js
@@ -0,0 +1,27 @@
+const path = pm.request.url.toString();
+const isPostRequest = pm.request.method.toString() === "POST";
+const isPaymentCreation = path.match(/\/payments$/) && isPostRequest;
+
+if (isPaymentCreation) {
+  try {
+    const request = JSON.parse(pm.request.body.toJSON().raw);
+
+    // Attach routing
+    const routing = { type: "single", data: "paypal" };
+    request["routing"] = routing;
+
+    let updatedRequest = {
+      mode: "raw",
+      raw: JSON.stringify(request),
+      options: {
+        raw: {
+          language: "json",
+        },
+      },
+    };
+    pm.request.body.update(updatedRequest);
+  } catch (error) {
+    console.error("Failed to inject routing in the request");
+    console.error(error);
+  }
+}
\ No newline at end of file
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/.meta.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/.meta.json
new file mode 100644
index 000000000000..69b505c6d863
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/.meta.json	
@@ -0,0 +1,3 @@
+{
+  "childrenOrder": ["Payments - Create", "Payments - Retrieve"]
+}
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Create/.event.meta.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Create/.event.meta.json
new file mode 100644
index 000000000000..0731450e6b25
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Create/.event.meta.json	
@@ -0,0 +1,3 @@
+{
+  "eventOrder": ["event.test.js"]
+}
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Create/event.test.js b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Create/event.test.js
new file mode 100644
index 000000000000..2be75ec0088b
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Create/event.test.js	
@@ -0,0 +1,100 @@
+// Validate status 2xx
+pm.test("[POST]::/payments - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[POST]::/payments - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[POST]::/payments - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "succeeded" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments - Content check if value for 'status' matches 'failed'",
+    function () {
+      pm.expect(jsonData.status).to.eql("failed");
+    },
+  );
+}
+
+// Response body should have "connector_transaction_id"
+pm.test(
+  "[POST]::/payments - Content check if 'connector_transaction_id' exists",
+  function () {
+    pm.expect(typeof jsonData.connector_transaction_id !== "undefined").to.be
+      .true;
+  },
+);
+
+// Response body should have value "card_declined" for "error_code"
+if (jsonData?.error_code) {
+  pm.test(
+    "[POST]::/payments/:id/confirm - Content check if value for 'error_code' matches 'card_declined'",
+    function () {
+      pm.expect(jsonData.error_code).to.eql("card_declined");
+    },
+  );
+}
+
+// Response body should have value "message - Your card has insufficient funds., decline_code - insufficient_funds" for "error_message"
+if (jsonData?.error_message) {
+  pm.test(
+    "[POST]::/payments/:id/confirm - Content check if value for 'error_message' matches 'message - Your card has insufficient funds., decline_code - insufficient_funds'",
+    function () {
+      pm.expect(jsonData.error_message).to.eql("message - Your card has insufficient funds., decline_code - insufficient_funds");
+    },
+  );
+}
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Create/request.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Create/request.json
new file mode 100644
index 000000000000..150139b8e104
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Create/request.json	
@@ -0,0 +1,94 @@
+{
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "amount": 6540,
+      "currency": "USD",
+      "confirm": true,
+      "business_country": "US",
+      "business_label": "default",
+      "capture_method": "automatic",
+      "capture_on": "2022-09-10T10:11:12Z",
+      "amount_to_capture": 1,
+      "customer_id": "bernard123",
+      "email": "guest@example.com",
+      "name": "John Doe",
+      "phone": "999999999",
+      "phone_country_code": "+65",
+      "description": "Its my first payment request",
+      "authentication_type": "no_three_ds",
+      "return_url": "https://duck.com",
+      "setup_future_usage": "on_session",
+      "payment_method": "card",
+      "payment_method_type": "debit",
+      "payment_method_data": {
+        "card": {
+          "card_number": "4000000000009995",
+          "card_exp_month": "01",
+          "card_exp_year": "24",
+          "card_holder_name": "joseph Doe",
+          "card_cvc": "123"
+        }
+      },
+      "billing": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "sundari",
+          "last_name": "sundari"
+        }
+      },
+      "shipping": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "sundari",
+          "last_name": "sundari"
+        }
+      },
+      "statement_descriptor_name": "joseph",
+      "statement_descriptor_suffix": "JS",
+      "metadata": {
+        "udf1": "value1",
+        "new_customer": "true",
+        "login_date": "2019-09-10T10:11:12Z"
+      },
+      "routing": {
+        "type": "single",
+        "data": "stripe"
+      }
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/payments",
+    "host": ["{{baseUrl}}"],
+    "path": ["payments"]
+  },
+  "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+}
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Create/response.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Create/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Create/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Retrieve/.event.meta.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Retrieve/.event.meta.json
new file mode 100644
index 000000000000..0731450e6b25
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Retrieve/.event.meta.json	
@@ -0,0 +1,3 @@
+{
+  "eventOrder": ["event.test.js"]
+}
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Retrieve/event.test.js b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Retrieve/event.test.js
new file mode 100644
index 000000000000..f8825a335742
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Retrieve/event.test.js	
@@ -0,0 +1,100 @@
+// Validate status 2xx
+pm.test("[GET]::/payments/:id - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[GET]::/payments/:id - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[GET]::/payments/:id - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "Succeeded" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments/:id - Content check if value for 'status' matches 'failed'",
+    function () {
+      pm.expect(jsonData.status).to.eql("failed");
+    },
+  );
+}
+
+// Response body should have "connector_transaction_id"
+pm.test(
+  "[POST]::/payments - Content check if 'connector_transaction_id' exists",
+  function () {
+    pm.expect(typeof jsonData.connector_transaction_id !== "undefined").to.be
+      .true;
+  },
+);
+
+// Response body should have value "card_declined" for "error_code"
+if (jsonData?.error_code) {
+  pm.test(
+    "[POST]::/payments/:id/confirm - Content check if value for 'error_code' matches 'card_declined'",
+    function () {
+      pm.expect(jsonData.error_code).to.eql("card_declined");
+    },
+  );
+}
+
+// Response body should have value "message - Your card has insufficient funds., decline_code - insufficient_funds" for "error_message"
+if (jsonData?.error_message) {
+  pm.test(
+    "[POST]::/payments/:id/confirm - Content check if value for 'error_message' matches 'message - Your card has insufficient funds., decline_code - insufficient_funds'",
+    function () {
+      pm.expect(jsonData.error_message).to.eql("message - Your card has insufficient funds., decline_code - insufficient_funds");
+    },
+  );
+}
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Retrieve/request.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Retrieve/request.json
new file mode 100644
index 000000000000..6cd4b7d96c52
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Retrieve/request.json	
@@ -0,0 +1,28 @@
+{
+  "method": "GET",
+  "header": [
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "url": {
+    "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+    "host": ["{{baseUrl}}"],
+    "path": ["payments", ":id"],
+    "query": [
+      {
+        "key": "force_sync",
+        "value": "true"
+      }
+    ],
+    "variable": [
+      {
+        "key": "id",
+        "value": "{{payment_id}}",
+        "description": "(Required) unique payment id"
+      }
+    ]
+  },
+  "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+}
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Retrieve/response.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Retrieve/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create a failure card payment with confirm true/Payments - Retrieve/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/.meta.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/.meta.json
new file mode 100644
index 000000000000..60051ecca220
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/.meta.json	
@@ -0,0 +1,6 @@
+{
+  "childrenOrder": [
+    "Payments - Create",
+    "Payments - Retrieve"
+  ]
+}
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Create/.event.meta.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Create/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Create/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Create/event.test.js b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Create/event.test.js
new file mode 100644
index 000000000000..ffcdd527d07c
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Create/event.test.js	
@@ -0,0 +1,80 @@
+// Validate status 2xx
+pm.test("[POST]::/payments - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[POST]::/payments - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[POST]::/payments - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "succeeded" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments - Content check if value for 'status' matches 'succeeded'",
+    function () {
+      pm.expect(jsonData.status).to.eql("succeeded");
+    },
+  );
+}
+
+// Response body should have "connector_transaction_id"
+pm.test(
+  "[POST]::/payments - Content check if 'connector_transaction_id' exists",
+  function () {
+    pm.expect(typeof jsonData.connector_transaction_id !== "undefined").to.be
+      .true;
+  },
+);
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Create/request.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Create/request.json
new file mode 100644
index 000000000000..21f054843897
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Create/request.json	
@@ -0,0 +1,98 @@
+{
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "amount": 6540,
+      "currency": "USD",
+      "confirm": true,
+      "business_country": "US",
+      "business_label": "default",
+      "capture_method": "automatic",
+      "capture_on": "2022-09-10T10:11:12Z",
+      "amount_to_capture": 1,
+      "customer_id": "bernard123",
+      "email": "guest@example.com",
+      "name": "John Doe",
+      "phone": "999999999",
+      "phone_country_code": "+65",
+      "description": "Its my first payment request",
+      "authentication_type": "no_three_ds",
+      "return_url": "https://duck.com",
+      "setup_future_usage": "on_session",
+      "payment_method": "card",
+      "payment_method_type": "debit",
+      "payment_method_data": {
+        "card": {
+          "card_number": "4242424242424242",
+          "card_exp_month": "01",
+          "card_exp_year": "24",
+          "card_holder_name": "joseph Doe",
+          "card_cvc": "123"
+        }
+      },
+      "billing": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "sundari",
+          "last_name": "sundari"
+        }
+      },
+      "shipping": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "sundari",
+          "last_name": "sundari"
+        }
+      },
+      "statement_descriptor_name": "joseph",
+      "statement_descriptor_suffix": "JS",
+      "metadata": {
+        "udf1": "value1",
+        "new_customer": "true",
+        "login_date": "2019-09-10T10:11:12Z"
+      },
+      "routing": {
+        "type": "single",
+        "data": "stripe"
+      }
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/payments",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments"
+    ]
+  },
+  "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+}
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Create/response.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Create/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Create/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Retrieve/.event.meta.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Retrieve/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Retrieve/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Retrieve/event.test.js b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Retrieve/event.test.js
new file mode 100644
index 000000000000..20626ecd2a9c
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Retrieve/event.test.js	
@@ -0,0 +1,80 @@
+// Validate status 2xx
+pm.test("[GET]::/payments/:id - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[GET]::/payments/:id - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[GET]::/payments/:id - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "Succeeded" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments/:id - Content check if value for 'status' matches 'succeeded'",
+    function () {
+      pm.expect(jsonData.status).to.eql("succeeded");
+    },
+  );
+}
+
+// Response body should have "connector_transaction_id"
+pm.test(
+  "[POST]::/payments - Content check if 'connector_transaction_id' exists",
+  function () {
+    pm.expect(typeof jsonData.connector_transaction_id !== "undefined").to.be
+      .true;
+  },
+);
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Retrieve/request.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Retrieve/request.json
new file mode 100644
index 000000000000..b9ebc1be4aa3
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Retrieve/request.json	
@@ -0,0 +1,33 @@
+{
+  "method": "GET",
+  "header": [
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "url": {
+    "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments",
+      ":id"
+    ],
+    "query": [
+      {
+        "key": "force_sync",
+        "value": "true"
+      }
+    ],
+    "variable": [
+      {
+        "key": "id",
+        "value": "{{payment_id}}",
+        "description": "(Required) unique payment id"
+      }
+    ]
+  },
+  "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+}
diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Retrieve/response.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Retrieve/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario27-Create payment without customer_id and with billing address and shipping address/Payments - Retrieve/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/stripe/MerchantAccounts/.meta.json b/postman/collection-dir/stripe/MerchantAccounts/.meta.json
index ef71d120e462..02ea600d2eb8 100644
--- a/postman/collection-dir/stripe/MerchantAccounts/.meta.json
+++ b/postman/collection-dir/stripe/MerchantAccounts/.meta.json
@@ -2,6 +2,7 @@
   "childrenOrder": [
     "Merchant Account - Create",
     "Merchant Account - Retrieve",
+    "Merchant Account - List",
     "Merchant Account - Update"
   ]
 }
diff --git a/postman/collection-dir/stripe/MerchantAccounts/Merchant Account - Create/event.test.js b/postman/collection-dir/stripe/MerchantAccounts/Merchant Account - Create/event.test.js
index 9c5a8900dc03..41eecccf83fc 100644
--- a/postman/collection-dir/stripe/MerchantAccounts/Merchant Account - Create/event.test.js	
+++ b/postman/collection-dir/stripe/MerchantAccounts/Merchant Account - Create/event.test.js	
@@ -67,3 +67,11 @@ if (jsonData?.merchant_id) {
     "INFO - Unable to assign variable {{organization_id}}, as jsonData.organization_id is undefined.",
   );
 }
+
+// Response body should have "mandate_id"
+pm.test(
+  "[POST]::/accounts - Organization id is generated",
+  function () {
+    pm.expect(typeof jsonData.organization_id !== "undefined").to.be.true;
+  },
+);
diff --git a/postman/collection-dir/stripe/QuickStart/Refunds - Create/event.test.js b/postman/collection-dir/stripe/QuickStart/Refunds - Create/event.test.js
index dbc930608cb3..f88e7ae9d6af 100644
--- a/postman/collection-dir/stripe/QuickStart/Refunds - Create/event.test.js	
+++ b/postman/collection-dir/stripe/QuickStart/Refunds - Create/event.test.js	
@@ -28,3 +28,13 @@ if (jsonData?.refund_id) {
     "INFO - Unable to assign variable {{refund_id}}, as jsonData.refund_id is undefined.",
   );
 }
+
+
+// Response body should have "profile_id" and not "null"
+pm.test(
+  "[POST]::/payments - Content check if 'profile_id' exists and is not 'null'",
+  function () {
+    pm.expect(typeof jsonData.profile_id !== "undefined").to.be.true;
+    pm.expect(jsonData.profile_id).is.not.null;
+  },
+);
diff --git a/postman/collection-dir/volt/.auth.json b/postman/collection-dir/volt/.auth.json
new file mode 100644
index 000000000000..915a28357900
--- /dev/null
+++ b/postman/collection-dir/volt/.auth.json
@@ -0,0 +1,22 @@
+{
+  "auth": {
+    "type": "apikey",
+    "apikey": [
+      {
+        "key": "value",
+        "value": "{{api_key}}",
+        "type": "string"
+      },
+      {
+        "key": "key",
+        "value": "api-key",
+        "type": "string"
+      },
+      {
+        "key": "in",
+        "value": "header",
+        "type": "string"
+      }
+    ]
+  }
+}
diff --git a/postman/collection-dir/volt/.event.meta.json b/postman/collection-dir/volt/.event.meta.json
new file mode 100644
index 000000000000..2df9d47d936d
--- /dev/null
+++ b/postman/collection-dir/volt/.event.meta.json
@@ -0,0 +1,6 @@
+{
+  "eventOrder": [
+    "event.prerequest.js",
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/.info.json b/postman/collection-dir/volt/.info.json
new file mode 100644
index 000000000000..802b98a9e8f6
--- /dev/null
+++ b/postman/collection-dir/volt/.info.json
@@ -0,0 +1,9 @@
+{
+  "info": {
+    "_postman_id": "ac5a089e-b4a3-43b2-8938-b2e44056e455",
+    "name": "volt",
+    "description": "## Get started\n\nJuspay Router provides a collection of APIs that enable you to process and manage payments. Our APIs accept and return JSON in the HTTP body, and return standard HTTP response codes.  \nYou can consume the APIs directly using your favorite HTTP/REST library.  \nWe have a testing environment referred to \"sandbox\", which you can setup to test API calls without affecting production data.\n\n### Base URLs\n\nUse the following base URLs when making requests to the APIs:\n\n| Environment | Base URL |\n| --- | --- |\n| Sandbox | [https://sandbox.hyperswitch.io](https://sandbox.hyperswitch.io) |\n| Production | [https://router.juspay.io](https://router.juspay.io) |\n\n# Authentication\n\nWhen you sign up for an account, you are given a secret key (also referred as api-key). You may authenticate all API requests with Juspay server by providing the appropriate key in the request Authorization header.  \nNever share your secret api keys. Keep them guarded and secure.\n\nContact Support:  \nName: Juspay Support  \nEmail: [support@juspay.in](mailto:support@juspay.in)",
+    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+    "_exporter_id": "27008363"
+  }
+}
diff --git a/postman/collection-dir/volt/.meta.json b/postman/collection-dir/volt/.meta.json
new file mode 100644
index 000000000000..91b6a65c5bc6
--- /dev/null
+++ b/postman/collection-dir/volt/.meta.json
@@ -0,0 +1,6 @@
+{
+  "childrenOrder": [
+    "Health check",
+    "Flow Testcases"
+  ]
+}
diff --git a/postman/collection-dir/volt/.variable.json b/postman/collection-dir/volt/.variable.json
new file mode 100644
index 000000000000..755dab38d54a
--- /dev/null
+++ b/postman/collection-dir/volt/.variable.json
@@ -0,0 +1,101 @@
+{
+  "variable": [
+    {
+      "key": "baseUrl",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "admin_api_key",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "api_key",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "merchant_id",
+      "value": ""
+    },
+    {
+      "key": "payment_id",
+      "value": ""
+    },
+    {
+      "key": "customer_id",
+      "value": ""
+    },
+    {
+      "key": "mandate_id",
+      "value": ""
+    },
+    {
+      "key": "payment_method_id",
+      "value": ""
+    },
+    {
+      "key": "refund_id",
+      "value": ""
+    },
+    {
+      "key": "merchant_connector_id",
+      "value": ""
+    },
+    {
+      "key": "client_secret",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "connector_api_key",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "connector_api_secret",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "connector_key1",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "connector_key2",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "publishable_key",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "api_key_id",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "payment_token",
+      "value": ""
+    },
+    {
+      "key": "gateway_merchant_id",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "certificate",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "certificate_keys",
+      "value": "",
+      "type": "string"
+    }
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/.meta.json b/postman/collection-dir/volt/Flow Testcases/.meta.json
new file mode 100644
index 000000000000..bd972090b19e
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/.meta.json	
@@ -0,0 +1,6 @@
+{
+  "childrenOrder": [
+    "QuickStart",
+    "Happy Cases"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/.meta.json
new file mode 100644
index 000000000000..2429b1c3988c
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/.meta.json	
@@ -0,0 +1,8 @@
+{
+  "childrenOrder": [
+    "Scenario1-Create payment with confirm true",
+    "Scenario2-Create payment with confirm false",
+    "Scenario3-Create payment without PMD",
+    "Scenario4-Bank Redirect-open_banking_uk"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/.meta.json
new file mode 100644
index 000000000000..60051ecca220
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/.meta.json	
@@ -0,0 +1,6 @@
+{
+  "childrenOrder": [
+    "Payments - Create",
+    "Payments - Retrieve"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/event.test.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/event.test.js
new file mode 100644
index 000000000000..3fd8b3c7cbe6
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/event.test.js	
@@ -0,0 +1,80 @@
+// Validate status 2xx
+pm.test("[POST]::/payments - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[POST]::/payments - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[POST]::/payments - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "requires_customer_action" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments - Content check if value for 'status' matches 'requires_customer_action'",
+    function () {
+      pm.expect(jsonData.status).to.eql("requires_customer_action");
+    },
+  );
+}
+
+// Response body should have "connector_transaction_id"
+pm.test(
+  "[POST]::/payments - Content check if 'connector_transaction_id' exists",
+  function () {
+    pm.expect(typeof jsonData.connector_transaction_id !== "undefined").to.be
+      .true;
+  },
+);
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/request.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/request.json
new file mode 100644
index 000000000000..6bfc68500963
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/request.json	
@@ -0,0 +1,102 @@
+{
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "amount": 6540,
+      "currency": "EUR",
+      "confirm": true,
+      "capture_method": "automatic",
+      "capture_on": "2022-09-10T10:11:12Z",
+      "amount_to_capture": 6540,
+      "customer_id": "StripeCustomer",
+      "email": "guest@example.com",
+      "name": "John Doe",
+      "phone": "999999999",
+      "phone_country_code": "+1",
+      "description": "Its my first payment request",
+      "authentication_type": "no_three_ds",
+      "return_url": "https://google.com",
+      "payment_method": "bank_redirect",
+      "payment_method_type": "open_banking_uk",
+      "payment_method_data": {
+        "bank_redirect": {
+          "open_banking_uk": {
+            "issuer": "citi",
+            "country": "GB"
+          }
+        }
+      },
+      "billing": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "joseph",
+          "last_name": "Doe"
+        },
+        "phone": {
+          "number": "8056594427",
+          "country_code": "+91"
+        }
+      },
+      "shipping": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "joseph",
+          "last_name": "Doe"
+        },
+        "phone": {
+          "number": "8056594427",
+          "country_code": "+91"
+        }
+      },
+      "statement_descriptor_name": "joseph",
+      "statement_descriptor_suffix": "JS",
+      "metadata": {
+        "udf1": "value1",
+        "new_customer": "true",
+        "login_date": "2019-09-10T10:11:12Z"
+      },
+      "routing": {
+        "type": "single",
+        "data": "volt"
+      }
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/payments",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments"
+    ]
+  },
+  "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/response.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Create/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Retrieve/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Retrieve/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Retrieve/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Retrieve/event.test.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Retrieve/event.test.js
new file mode 100644
index 000000000000..d1f1dc048ae2
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Retrieve/event.test.js	
@@ -0,0 +1,80 @@
+// Validate status 2xx
+pm.test("[GET]::/payments/:id - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[GET]::/payments/:id - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[GET]::/payments/:id - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "requires_customer_action" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments/:id - Content check if value for 'status' matches 'requires_customer_action'",
+    function () {
+      pm.expect(jsonData.status).to.eql("requires_customer_action");
+    },
+  );
+}
+
+// Response body should have "connector_transaction_id"
+pm.test(
+  "[POST]::/payments - Content check if 'connector_transaction_id' exists",
+  function () {
+    pm.expect(typeof jsonData.connector_transaction_id !== "undefined").to.be
+      .true;
+  },
+);
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Retrieve/request.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Retrieve/request.json
new file mode 100644
index 000000000000..b9ebc1be4aa3
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Retrieve/request.json	
@@ -0,0 +1,33 @@
+{
+  "method": "GET",
+  "header": [
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "url": {
+    "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments",
+      ":id"
+    ],
+    "query": [
+      {
+        "key": "force_sync",
+        "value": "true"
+      }
+    ],
+    "variable": [
+      {
+        "key": "id",
+        "value": "{{payment_id}}",
+        "description": "(Required) unique payment id"
+      }
+    ]
+  },
+  "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Retrieve/response.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Retrieve/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario1-Create payment with confirm true/Payments - Retrieve/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/.meta.json
new file mode 100644
index 000000000000..57d3f8e2bc7e
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/.meta.json	
@@ -0,0 +1,7 @@
+{
+  "childrenOrder": [
+    "Payments - Create",
+    "Payments - Confirm",
+    "Payments - Retrieve"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/.event.meta.json
new file mode 100644
index 000000000000..4ac527d834af
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/.event.meta.json	
@@ -0,0 +1,6 @@
+{
+  "eventOrder": [
+    "event.test.js",
+    "event.prerequest.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/event.prerequest.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/event.prerequest.js
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/event.test.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/event.test.js
new file mode 100644
index 000000000000..6a2040fb5b82
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/event.test.js	
@@ -0,0 +1,103 @@
+// Validate status 2xx
+pm.test("[POST]::/payments/:id/confirm - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test(
+  "[POST]::/payments/:id/confirm - Content-Type is application/json",
+  function () {
+    pm.expect(pm.response.headers.get("Content-Type")).to.include(
+      "application/json",
+    );
+  },
+);
+
+// Validate if response has JSON Body
+pm.test("[POST]::/payments/:id/confirm - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "6540" for "amount"
+if (jsonData?.amount) {
+  pm.test(
+    "[post]:://payments/:id/capture - Content check if value for 'amount' matches '6540'",
+    function () {
+      pm.expect(jsonData.amount).to.eql(6540);
+    },
+  );
+}
+
+// Response body should have value "6540" for "amount_capturable"
+if (jsonData?.amount) {
+  pm.test(
+    "[post]:://payments/:id/capture - Content check if value for 'amount_capturable' matches 'amount - 6540'",
+    function () {
+      pm.expect(jsonData.amount_capturable).to.eql(6540);
+    },
+  );
+}
+
+// Response body should have value "requires_customer_action" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments/:id/confirm - Content check if value for 'status' matches 'requires_customer_action'",
+    function () {
+      pm.expect(jsonData.status).to.eql("requires_customer_action");
+    },
+  );
+}
+
+// Response body should have "connector_transaction_id"
+pm.test(
+  "[POST]::/payments - Content check if 'connector_transaction_id' exists",
+  function () {
+    pm.expect(typeof jsonData.connector_transaction_id !== "undefined").to.be
+      .true;
+  },
+);
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/request.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/request.json
new file mode 100644
index 000000000000..16f6e13983f8
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/request.json	
@@ -0,0 +1,63 @@
+{
+  "auth": {
+    "type": "apikey",
+    "apikey": [
+      {
+        "key": "value",
+        "value": "{{publishable_key}}",
+        "type": "string"
+      },
+      {
+        "key": "key",
+        "value": "api-key",
+        "type": "string"
+      },
+      {
+        "key": "in",
+        "value": "header",
+        "type": "string"
+      }
+    ]
+  },
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "client_secret": "{{client_secret}}"
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/payments/:id/confirm",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments",
+      ":id",
+      "confirm"
+    ],
+    "variable": [
+      {
+        "key": "id",
+        "value": "{{payment_id}}",
+        "description": "(Required) unique payment id"
+      }
+    ]
+  },
+  "description": "This API is to confirm the payment request and forward payment to the payment processor. This API provides more granular control upon when the API is forwarded to the payment processor. Alternatively you can confirm the payment within the Payments-Create API"
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/response.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Confirm/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/event.test.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/event.test.js
new file mode 100644
index 000000000000..55dc35b91280
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/event.test.js	
@@ -0,0 +1,71 @@
+// Validate status 2xx
+pm.test("[POST]::/payments - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[POST]::/payments - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[POST]::/payments - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "requires_confirmation" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments - Content check if value for 'status' matches 'requires_confirmation'",
+    function () {
+      pm.expect(jsonData.status).to.eql("requires_confirmation");
+    },
+  );
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/request.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/request.json
new file mode 100644
index 000000000000..a4192d96b4a7
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/request.json	
@@ -0,0 +1,102 @@
+{
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "amount": 6540,
+      "currency": "EUR",
+      "confirm": false,
+      "capture_method": "automatic",
+      "capture_on": "2022-09-10T10:11:12Z",
+      "amount_to_capture": 6540,
+      "customer_id": "StripeCustomer",
+      "email": "guest@example.com",
+      "name": "John Doe",
+      "phone": "999999999",
+      "phone_country_code": "+1",
+      "description": "Its my first payment request",
+      "authentication_type": "no_three_ds",
+      "return_url": "https://google.com",
+      "payment_method": "bank_redirect",
+      "payment_method_type": "open_banking_uk",
+      "payment_method_data": {
+        "bank_redirect": {
+          "open_banking_uk": {
+            "issuer": "citi",
+            "country": "GB"
+          }
+        }
+      },
+      "billing": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "joseph",
+          "last_name": "Doe"
+        },
+        "phone": {
+          "number": "8056594427",
+          "country_code": "+91"
+        }
+      },
+      "shipping": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "joseph",
+          "last_name": "Doe"
+        },
+        "phone": {
+          "number": "8056594427",
+          "country_code": "+91"
+        }
+      },
+      "statement_descriptor_name": "joseph",
+      "statement_descriptor_suffix": "JS",
+      "metadata": {
+        "udf1": "value1",
+        "new_customer": "true",
+        "login_date": "2019-09-10T10:11:12Z"
+      },
+      "routing": {
+        "type": "single",
+        "data": "volt"
+      }
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/payments",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments"
+    ]
+  },
+  "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/response.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Create/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Retrieve/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Retrieve/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Retrieve/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Retrieve/event.test.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Retrieve/event.test.js
new file mode 100644
index 000000000000..0463f0e86c0a
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Retrieve/event.test.js	
@@ -0,0 +1,91 @@
+// Validate status 2xx
+pm.test("[GET]::/payments/:id - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[GET]::/payments/:id - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[GET]::/payments/:id - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "requires_customer_action" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments:id - Content check if value for 'status' matches 'requires_customer_action'",
+    function () {
+      pm.expect(jsonData.status).to.eql("requires_customer_action");
+    },
+  );
+}
+
+// Response body should have value "6540" for "amount"
+if (jsonData?.amount) {
+  pm.test(
+    "[post]:://payments/:id/capture - Content check if value for 'amount' matches '6540'",
+    function () {
+      pm.expect(jsonData.amount).to.eql(6540);
+    },
+  );
+}
+
+// Response body should have value "6540" for "amount_capturable"
+if (jsonData?.amount) {
+  pm.test(
+    "[post]:://payments/:id/capture - Content check if value for 'amount_capturable' matches 'amount - 6540'",
+    function () {
+      pm.expect(jsonData.amount_capturable).to.eql(6540);
+    },
+  );
+}
\ No newline at end of file
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Retrieve/request.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Retrieve/request.json
new file mode 100644
index 000000000000..b9ebc1be4aa3
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Retrieve/request.json	
@@ -0,0 +1,33 @@
+{
+  "method": "GET",
+  "header": [
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "url": {
+    "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments",
+      ":id"
+    ],
+    "query": [
+      {
+        "key": "force_sync",
+        "value": "true"
+      }
+    ],
+    "variable": [
+      {
+        "key": "id",
+        "value": "{{payment_id}}",
+        "description": "(Required) unique payment id"
+      }
+    ]
+  },
+  "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Retrieve/response.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Retrieve/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario2-Create payment with confirm false/Payments - Retrieve/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/.meta.json
new file mode 100644
index 000000000000..57d3f8e2bc7e
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/.meta.json	
@@ -0,0 +1,7 @@
+{
+  "childrenOrder": [
+    "Payments - Create",
+    "Payments - Confirm",
+    "Payments - Retrieve"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/.event.meta.json
new file mode 100644
index 000000000000..4ac527d834af
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/.event.meta.json	
@@ -0,0 +1,6 @@
+{
+  "eventOrder": [
+    "event.test.js",
+    "event.prerequest.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/event.prerequest.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/event.prerequest.js
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/event.test.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/event.test.js
new file mode 100644
index 000000000000..8bbfce6d5b59
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/event.test.js	
@@ -0,0 +1,73 @@
+// Validate status 2xx
+pm.test("[POST]::/payments/:id/confirm - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test(
+  "[POST]::/payments/:id/confirm - Content-Type is application/json",
+  function () {
+    pm.expect(pm.response.headers.get("Content-Type")).to.include(
+      "application/json",
+    );
+  },
+);
+
+// Validate if response has JSON Body
+pm.test("[POST]::/payments/:id/confirm - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+// Response body should have value "requires_customer_action" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments:id/confirm - Content check if value for 'status' matches 'requires_customer_action'",
+    function () {
+      pm.expect(jsonData.status).to.eql("requires_customer_action");
+    },
+  );
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/request.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/request.json
new file mode 100644
index 000000000000..f0f67b12fb46
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/request.json	
@@ -0,0 +1,73 @@
+{
+  "auth": {
+    "type": "apikey",
+    "apikey": [
+      {
+        "key": "value",
+        "value": "{{publishable_key}}",
+        "type": "string"
+      },
+      {
+        "key": "key",
+        "value": "api-key",
+        "type": "string"
+      },
+      {
+        "key": "in",
+        "value": "header",
+        "type": "string"
+      }
+    ]
+  },
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "payment_method": "bank_redirect",
+      "payment_method_type": "open_banking_uk",
+      "payment_method_data": {
+        "bank_redirect": {
+          "open_banking_uk": {
+            "issuer": "citi",
+            "country": "GB"
+          }
+        }
+      },
+      "client_secret": "{{client_secret}}"
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/payments/:id/confirm",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments",
+      ":id",
+      "confirm"
+    ],
+    "variable": [
+      {
+        "key": "id",
+        "value": "{{payment_id}}",
+        "description": "(Required) unique payment id"
+      }
+    ]
+  },
+  "description": "This API is to confirm the payment request and forward payment to the payment processor. This API provides more granular control upon when the API is forwarded to the payment processor. Alternatively you can confirm the payment within the Payments-Create API"
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/response.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Confirm/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Create/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Create/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Create/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Create/event.test.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Create/event.test.js
new file mode 100644
index 000000000000..0444324000a6
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Create/event.test.js	
@@ -0,0 +1,71 @@
+// Validate status 2xx
+pm.test("[POST]::/payments - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[POST]::/payments - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[POST]::/payments - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "requires_payment_method" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments - Content check if value for 'status' matches 'requires_payment_method'",
+    function () {
+      pm.expect(jsonData.status).to.eql("requires_payment_method");
+    },
+  );
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Create/request.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Create/request.json
new file mode 100644
index 000000000000..7323f440e645
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Create/request.json	
@@ -0,0 +1,83 @@
+{
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "amount": 6540,
+      "currency": "EUR",
+      "confirm": false,
+      "capture_method": "automatic",
+      "capture_on": "2022-09-10T10:11:12Z",
+      "amount_to_capture": 6540,
+      "customer_id": "StripeCustomer",
+      "email": "guest@example.com",
+      "name": "John Doe",
+      "phone": "999999999",
+      "phone_country_code": "+1",
+      "description": "Its my first payment request",
+      "authentication_type": "no_three_ds",
+      "return_url": "https://google.com",
+      "billing": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "sundari",
+          "last_name": "singh"
+        }
+      },
+      "shipping": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "sundari"
+        }
+      },
+      "statement_descriptor_name": "joseph",
+      "statement_descriptor_suffix": "JS",
+      "metadata": {
+        "udf1": "value1",
+        "new_customer": "true",
+        "login_date": "2019-09-10T10:11:12Z"
+      },
+      "routing": {
+        "type": "single",
+        "data": "volt"
+      }
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/payments",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments"
+    ]
+  },
+  "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Create/response.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Create/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Create/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Retrieve/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Retrieve/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Retrieve/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Retrieve/event.test.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Retrieve/event.test.js
new file mode 100644
index 000000000000..9053ddab13be
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Retrieve/event.test.js	
@@ -0,0 +1,71 @@
+// Validate status 2xx
+pm.test("[GET]::/payments/:id - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[GET]::/payments/:id - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[GET]::/payments/:id - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "requires_customer_action" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments:id - Content check if value for 'status' matches 'requires_customer_action'",
+    function () {
+      pm.expect(jsonData.status).to.eql("requires_customer_action");
+    },
+  );
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Retrieve/request.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Retrieve/request.json
new file mode 100644
index 000000000000..b9ebc1be4aa3
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Retrieve/request.json	
@@ -0,0 +1,33 @@
+{
+  "method": "GET",
+  "header": [
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "url": {
+    "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments",
+      ":id"
+    ],
+    "query": [
+      {
+        "key": "force_sync",
+        "value": "true"
+      }
+    ],
+    "variable": [
+      {
+        "key": "id",
+        "value": "{{payment_id}}",
+        "description": "(Required) unique payment id"
+      }
+    ]
+  },
+  "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Retrieve/response.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Retrieve/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario3-Create payment without PMD/Payments - Retrieve/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/.meta.json
new file mode 100644
index 000000000000..57d3f8e2bc7e
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/.meta.json	
@@ -0,0 +1,7 @@
+{
+  "childrenOrder": [
+    "Payments - Create",
+    "Payments - Confirm",
+    "Payments - Retrieve"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/.event.meta.json
new file mode 100644
index 000000000000..4ac527d834af
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/.event.meta.json	
@@ -0,0 +1,6 @@
+{
+  "eventOrder": [
+    "event.test.js",
+    "event.prerequest.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/event.prerequest.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/event.prerequest.js
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/event.test.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/event.test.js
new file mode 100644
index 000000000000..9624b67240a6
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/event.test.js	
@@ -0,0 +1,103 @@
+// Validate status 2xx
+pm.test("[POST]::/payments/:id/confirm - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test(
+  "[POST]::/payments/:id/confirm - Content-Type is application/json",
+  function () {
+    pm.expect(pm.response.headers.get("Content-Type")).to.include(
+      "application/json",
+    );
+  },
+);
+
+// Validate if response has JSON Body
+pm.test("[POST]::/payments/:id/confirm - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "requires_customer_action" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments/:id/confirm - Content check if value for 'status' matches 'requires_customer_action'",
+    function () {
+      pm.expect(jsonData.status).to.eql("requires_customer_action");
+    },
+  );
+}
+
+// Response body should have "next_action.redirect_to_url"
+pm.test(
+  "[POST]::/payments - Content check if 'next_action.redirect_to_url' exists",
+  function () {
+    pm.expect(typeof jsonData.next_action.redirect_to_url !== "undefined").to.be
+      .true;
+  },
+);
+
+// Response body should have value "open_banking_uk" for "payment_method_type"
+if (jsonData?.payment_method_type) {
+  pm.test(
+    "[POST]::/payments/:id/confirm - Content check if value for 'payment_method_type' matches 'open_banking_uk'",
+    function () {
+      pm.expect(jsonData.payment_method_type).to.eql("open_banking_uk");
+    },
+  );
+}
+
+// Response body should have value "volt" for "connector"
+if (jsonData?.connector) {
+  pm.test(
+    "[POST]::/payments/:id/confirm - Content check if value for 'connector' matches 'volt'",
+    function () {
+      pm.expect(jsonData.connector).to.eql("volt");
+    },
+  );
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/request.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/request.json
new file mode 100644
index 000000000000..f0f67b12fb46
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/request.json	
@@ -0,0 +1,73 @@
+{
+  "auth": {
+    "type": "apikey",
+    "apikey": [
+      {
+        "key": "value",
+        "value": "{{publishable_key}}",
+        "type": "string"
+      },
+      {
+        "key": "key",
+        "value": "api-key",
+        "type": "string"
+      },
+      {
+        "key": "in",
+        "value": "header",
+        "type": "string"
+      }
+    ]
+  },
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "payment_method": "bank_redirect",
+      "payment_method_type": "open_banking_uk",
+      "payment_method_data": {
+        "bank_redirect": {
+          "open_banking_uk": {
+            "issuer": "citi",
+            "country": "GB"
+          }
+        }
+      },
+      "client_secret": "{{client_secret}}"
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/payments/:id/confirm",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments",
+      ":id",
+      "confirm"
+    ],
+    "variable": [
+      {
+        "key": "id",
+        "value": "{{payment_id}}",
+        "description": "(Required) unique payment id"
+      }
+    ]
+  },
+  "description": "This API is to confirm the payment request and forward payment to the payment processor. This API provides more granular control upon when the API is forwarded to the payment processor. Alternatively you can confirm the payment within the Payments-Create API"
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/response.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Confirm/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Create/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Create/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Create/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Create/event.test.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Create/event.test.js
new file mode 100644
index 000000000000..0444324000a6
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Create/event.test.js	
@@ -0,0 +1,71 @@
+// Validate status 2xx
+pm.test("[POST]::/payments - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[POST]::/payments - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[POST]::/payments - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "requires_payment_method" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments - Content check if value for 'status' matches 'requires_payment_method'",
+    function () {
+      pm.expect(jsonData.status).to.eql("requires_payment_method");
+    },
+  );
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Create/request.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Create/request.json
new file mode 100644
index 000000000000..7323f440e645
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Create/request.json	
@@ -0,0 +1,83 @@
+{
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "amount": 6540,
+      "currency": "EUR",
+      "confirm": false,
+      "capture_method": "automatic",
+      "capture_on": "2022-09-10T10:11:12Z",
+      "amount_to_capture": 6540,
+      "customer_id": "StripeCustomer",
+      "email": "guest@example.com",
+      "name": "John Doe",
+      "phone": "999999999",
+      "phone_country_code": "+1",
+      "description": "Its my first payment request",
+      "authentication_type": "no_three_ds",
+      "return_url": "https://google.com",
+      "billing": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "sundari",
+          "last_name": "singh"
+        }
+      },
+      "shipping": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "sundari"
+        }
+      },
+      "statement_descriptor_name": "joseph",
+      "statement_descriptor_suffix": "JS",
+      "metadata": {
+        "udf1": "value1",
+        "new_customer": "true",
+        "login_date": "2019-09-10T10:11:12Z"
+      },
+      "routing": {
+        "type": "single",
+        "data": "volt"
+      }
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/payments",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments"
+    ]
+  },
+  "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Create/response.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Create/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Create/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Retrieve/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Retrieve/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Retrieve/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Retrieve/event.test.js b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Retrieve/event.test.js
new file mode 100644
index 000000000000..9053ddab13be
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Retrieve/event.test.js	
@@ -0,0 +1,71 @@
+// Validate status 2xx
+pm.test("[GET]::/payments/:id - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[GET]::/payments/:id - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[GET]::/payments/:id - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
+
+// Response body should have value "requires_customer_action" for "status"
+if (jsonData?.status) {
+  pm.test(
+    "[POST]::/payments:id - Content check if value for 'status' matches 'requires_customer_action'",
+    function () {
+      pm.expect(jsonData.status).to.eql("requires_customer_action");
+    },
+  );
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Retrieve/request.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Retrieve/request.json
new file mode 100644
index 000000000000..b9ebc1be4aa3
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Retrieve/request.json	
@@ -0,0 +1,33 @@
+{
+  "method": "GET",
+  "header": [
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "url": {
+    "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments",
+      ":id"
+    ],
+    "query": [
+      {
+        "key": "force_sync",
+        "value": "true"
+      }
+    ],
+    "variable": [
+      {
+        "key": "id",
+        "value": "{{payment_id}}",
+        "description": "(Required) unique payment id"
+      }
+    ]
+  },
+  "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Retrieve/response.json b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Retrieve/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/Happy Cases/Scenario4-Bank Redirect-open_banking_uk/Payments - Retrieve/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/.meta.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/.meta.json
new file mode 100644
index 000000000000..e3596ba357bc
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/.meta.json	
@@ -0,0 +1,9 @@
+{
+  "childrenOrder": [
+    "Merchant Account - Create",
+    "API Key - Create",
+    "Payment Connector - Create",
+    "Payments - Create",
+    "Payments - Retrieve"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/API Key - Create/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/API Key - Create/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/API Key - Create/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/API Key - Create/event.test.js b/postman/collection-dir/volt/Flow Testcases/QuickStart/API Key - Create/event.test.js
new file mode 100644
index 000000000000..4e27c5a50253
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/API Key - Create/event.test.js	
@@ -0,0 +1,46 @@
+// Validate status 2xx
+pm.test("[POST]::/api_keys/:merchant_id - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test(
+  "[POST]::/api_keys/:merchant_id - Content-Type is application/json",
+  function () {
+    pm.expect(pm.response.headers.get("Content-Type")).to.include(
+      "application/json",
+    );
+  },
+);
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set api_key_id as variable for jsonData.key_id
+if (jsonData?.key_id) {
+  pm.collectionVariables.set("api_key_id", jsonData.key_id);
+  console.log(
+    "- use {{api_key_id}} as collection variable for value",
+    jsonData.key_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{api_key_id}}, as jsonData.key_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set api_key as variable for jsonData.api_key
+if (jsonData?.api_key) {
+  pm.collectionVariables.set("api_key", jsonData.api_key);
+  console.log(
+    "- use {{api_key}} as collection variable for value",
+    jsonData.api_key,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{api_key}}, as jsonData.api_key is undefined.",
+  );
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/API Key - Create/request.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/API Key - Create/request.json
new file mode 100644
index 000000000000..b89ff6896855
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/API Key - Create/request.json	
@@ -0,0 +1,52 @@
+{
+  "auth": {
+    "type": "apikey",
+    "apikey": [
+      {
+        "key": "value",
+        "value": "{{admin_api_key}}",
+        "type": "string"
+      },
+      {
+        "key": "key",
+        "value": "api-key",
+        "type": "string"
+      }
+    ]
+  },
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "raw_json_formatted": {
+      "name": "API Key 1",
+      "description": null,
+      "expiration": "2099-09-23T01:02:03.000Z"
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/api_keys/:merchant_id",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "api_keys",
+      ":merchant_id"
+    ],
+    "variable": [
+      {
+        "key": "merchant_id",
+        "value": "{{merchant_id}}"
+      }
+    ]
+  }
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/API Key - Create/response.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/API Key - Create/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/API Key - Create/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Merchant Account - Create/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/Merchant Account - Create/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Merchant Account - Create/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Merchant Account - Create/event.test.js b/postman/collection-dir/volt/Flow Testcases/QuickStart/Merchant Account - Create/event.test.js
new file mode 100644
index 000000000000..7de0d5beb316
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Merchant Account - Create/event.test.js	
@@ -0,0 +1,56 @@
+// Validate status 2xx
+pm.test("[POST]::/accounts - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[POST]::/accounts - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set merchant_id as variable for jsonData.merchant_id
+if (jsonData?.merchant_id) {
+  pm.collectionVariables.set("merchant_id", jsonData.merchant_id);
+  console.log(
+    "- use {{merchant_id}} as collection variable for value",
+    jsonData.merchant_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{merchant_id}}, as jsonData.merchant_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set api_key as variable for jsonData.api_key
+if (jsonData?.api_key) {
+  pm.collectionVariables.set("api_key", jsonData.api_key);
+  console.log(
+    "- use {{api_key}} as collection variable for value",
+    jsonData.api_key,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{api_key}}, as jsonData.api_key is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set publishable_key as variable for jsonData.publishable_key
+if (jsonData?.publishable_key) {
+  pm.collectionVariables.set("publishable_key", jsonData.publishable_key);
+  console.log(
+    "- use {{publishable_key}} as collection variable for value",
+    jsonData.publishable_key,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{publishable_key}}, as jsonData.publishable_key is undefined.",
+  );
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Merchant Account - Create/request.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/Merchant Account - Create/request.json
new file mode 100644
index 000000000000..9f0ff5575c00
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Merchant Account - Create/request.json	
@@ -0,0 +1,95 @@
+{
+  "auth": {
+    "type": "apikey",
+    "apikey": [
+      {
+        "key": "value",
+        "value": "{{admin_api_key}}",
+        "type": "string"
+      },
+      {
+        "key": "key",
+        "value": "api-key",
+        "type": "string"
+      },
+      {
+        "key": "in",
+        "value": "header",
+        "type": "string"
+      }
+    ]
+  },
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "merchant_id": "postman_merchant_GHAction_{{$guid}}",
+      "locker_id": "m0010",
+      "merchant_name": "NewAge Retailer",
+      "merchant_details": {
+        "primary_contact_person": "John Test",
+        "primary_email": "JohnTest@test.com",
+        "primary_phone": "sunt laborum",
+        "secondary_contact_person": "John Test2",
+        "secondary_email": "JohnTest2@test.com",
+        "secondary_phone": "cillum do dolor id",
+        "website": "www.example.com",
+        "about_business": "Online Retail with a wide selection of organic products for North America",
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US"
+        }
+      },
+      "return_url": "https://duck.com",
+      "webhook_details": {
+        "webhook_version": "1.0.1",
+        "webhook_username": "ekart_retail",
+        "webhook_password": "password_ekart@123",
+        "payment_created_enabled": true,
+        "payment_succeeded_enabled": true,
+        "payment_failed_enabled": true
+      },
+      "sub_merchants_enabled": false,
+      "metadata": {
+        "city": "NY",
+        "unit": "245"
+      },
+      "primary_business_details": [
+        {
+          "country": "US",
+          "business": "default"
+        }
+      ]
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/accounts",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "accounts"
+    ]
+  },
+  "description": "Create a new account for a merchant. The merchant could be a seller or retailer or client who likes to receive and send payments."
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Merchant Account - Create/response.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/Merchant Account - Create/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Merchant Account - Create/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Payment Connector - Create/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payment Connector - Create/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payment Connector - Create/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Payment Connector - Create/event.test.js b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payment Connector - Create/event.test.js
new file mode 100644
index 000000000000..88e92d8d84a2
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payment Connector - Create/event.test.js	
@@ -0,0 +1,39 @@
+// Validate status 2xx
+pm.test(
+  "[POST]::/account/:account_id/connectors - Status code is 2xx",
+  function () {
+    pm.response.to.be.success;
+  },
+);
+
+// Validate if response header has matching content-type
+pm.test(
+  "[POST]::/account/:account_id/connectors - Content-Type is application/json",
+  function () {
+    pm.expect(pm.response.headers.get("Content-Type")).to.include(
+      "application/json",
+    );
+  },
+);
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set merchant_connector_id as variable for jsonData.merchant_connector_id
+if (jsonData?.merchant_connector_id) {
+  pm.collectionVariables.set(
+    "merchant_connector_id",
+    jsonData.merchant_connector_id,
+  );
+  console.log(
+    "- use {{merchant_connector_id}} as collection variable for value",
+    jsonData.merchant_connector_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{merchant_connector_id}}, as jsonData.merchant_connector_id is undefined.",
+  );
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Payment Connector - Create/request.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payment Connector - Create/request.json
new file mode 100644
index 000000000000..4c086eea1a6a
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payment Connector - Create/request.json	
@@ -0,0 +1,93 @@
+{
+  "auth": {
+    "type": "apikey",
+    "apikey": [
+      {
+        "key": "value",
+        "value": "{{admin_api_key}}",
+        "type": "string"
+      },
+      {
+        "key": "key",
+        "value": "api-key",
+        "type": "string"
+      },
+      {
+        "key": "in",
+        "value": "header",
+        "type": "string"
+      }
+    ]
+  },
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "connector_type": "fiz_operations",
+      "connector_name": "volt",
+      "business_country": "US",
+      "business_label": "default",
+      "connector_account_details": {
+        "auth_type": "MultiAuthKey",
+        "api_key": "{{connector_api_key}}",
+        "api_secret": "{{connector_api_secret}}",
+        "key1": "{{connector_key1}}",
+        "key2": "{{connector_key2}}"
+      },
+      "test_mode": false,
+      "disabled": false,
+      "payment_methods_enabled": [
+        {
+          "payment_method": "bank_redirect",
+          "payment_method_types": [
+            {
+              "payment_method_type": "open_banking_uk",
+              "payment_experience": null,
+              "card_networks": null,
+              "accepted_currencies": null,
+              "accepted_countries": null,
+              "minimum_amount": 1,
+              "maximum_amount": 68607706,
+              "recurring_enabled": true,
+              "installment_payment_enabled": true
+            }
+          ]
+        }
+      ]
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/account/:account_id/connectors",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "account",
+      ":account_id",
+      "connectors"
+    ],
+    "variable": [
+      {
+        "key": "account_id",
+        "value": "{{merchant_id}}",
+        "description": "(Required) The unique identifier for the merchant account"
+      }
+    ]
+  },
+  "description": "Create a new Payment Connector for the merchant account. The connector could be a payment processor / facilitator / acquirer or specialised services like Fraud / Accounting etc."
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Payment Connector - Create/response.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payment Connector - Create/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payment Connector - Create/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Create/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Create/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Create/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Create/event.test.js b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Create/event.test.js
new file mode 100644
index 000000000000..a6947db94c0b
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Create/event.test.js	
@@ -0,0 +1,61 @@
+// Validate status 2xx
+pm.test("[POST]::/payments - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[POST]::/payments - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Validate if response has JSON Body
+pm.test("[POST]::/payments - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Create/request.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Create/request.json
new file mode 100644
index 000000000000..6bfc68500963
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Create/request.json	
@@ -0,0 +1,102 @@
+{
+  "method": "POST",
+  "header": [
+    {
+      "key": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "body": {
+    "mode": "raw",
+    "options": {
+      "raw": {
+        "language": "json"
+      }
+    },
+    "raw_json_formatted": {
+      "amount": 6540,
+      "currency": "EUR",
+      "confirm": true,
+      "capture_method": "automatic",
+      "capture_on": "2022-09-10T10:11:12Z",
+      "amount_to_capture": 6540,
+      "customer_id": "StripeCustomer",
+      "email": "guest@example.com",
+      "name": "John Doe",
+      "phone": "999999999",
+      "phone_country_code": "+1",
+      "description": "Its my first payment request",
+      "authentication_type": "no_three_ds",
+      "return_url": "https://google.com",
+      "payment_method": "bank_redirect",
+      "payment_method_type": "open_banking_uk",
+      "payment_method_data": {
+        "bank_redirect": {
+          "open_banking_uk": {
+            "issuer": "citi",
+            "country": "GB"
+          }
+        }
+      },
+      "billing": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "joseph",
+          "last_name": "Doe"
+        },
+        "phone": {
+          "number": "8056594427",
+          "country_code": "+91"
+        }
+      },
+      "shipping": {
+        "address": {
+          "line1": "1467",
+          "line2": "Harrison Street",
+          "line3": "Harrison Street",
+          "city": "San Fransico",
+          "state": "California",
+          "zip": "94122",
+          "country": "US",
+          "first_name": "joseph",
+          "last_name": "Doe"
+        },
+        "phone": {
+          "number": "8056594427",
+          "country_code": "+91"
+        }
+      },
+      "statement_descriptor_name": "joseph",
+      "statement_descriptor_suffix": "JS",
+      "metadata": {
+        "udf1": "value1",
+        "new_customer": "true",
+        "login_date": "2019-09-10T10:11:12Z"
+      },
+      "routing": {
+        "type": "single",
+        "data": "volt"
+      }
+    }
+  },
+  "url": {
+    "raw": "{{baseUrl}}/payments",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments"
+    ]
+  },
+  "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Create/response.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Create/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Create/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Retrieve/.event.meta.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Retrieve/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Retrieve/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Retrieve/event.test.js b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Retrieve/event.test.js
new file mode 100644
index 000000000000..d0a02af74367
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Retrieve/event.test.js	
@@ -0,0 +1,61 @@
+// Validate status 2xx
+pm.test("[GET]::/payments/:id - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
+
+// Validate if response header has matching content-type
+pm.test("[GET]::/payments/:id - Content-Type is application/json", function () {
+  pm.expect(pm.response.headers.get("Content-Type")).to.include(
+    "application/json",
+  );
+});
+
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// Validate if response has JSON Body
+pm.test("[GET]::/payments/:id - Response has JSON Body", function () {
+  pm.response.to.have.jsonBody();
+});
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log(
+    "- use {{payment_id}} as collection variable for value",
+    jsonData.payment_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
+if (jsonData?.mandate_id) {
+  pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
+  console.log(
+    "- use {{mandate_id}} as collection variable for value",
+    jsonData.mandate_id,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
+  );
+}
+
+// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
+if (jsonData?.client_secret) {
+  pm.collectionVariables.set("client_secret", jsonData.client_secret);
+  console.log(
+    "- use {{client_secret}} as collection variable for value",
+    jsonData.client_secret,
+  );
+} else {
+  console.log(
+    "INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
+  );
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Retrieve/request.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Retrieve/request.json
new file mode 100644
index 000000000000..c71774083b2c
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Retrieve/request.json	
@@ -0,0 +1,27 @@
+{
+  "method": "GET",
+  "header": [
+    {
+      "key": "Accept",
+      "value": "application/json"
+    }
+  ],
+  "url": {
+    "raw": "{{baseUrl}}/payments/:id",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "payments",
+      ":id"
+    ],
+    "variable": [
+      {
+        "key": "id",
+        "value": "{{payment_id}}",
+        "description": "(Required) unique payment id"
+      }
+    ]
+  },
+  "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+}
diff --git a/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Retrieve/response.json b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Retrieve/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Flow Testcases/QuickStart/Payments - Retrieve/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/Health check/.meta.json b/postman/collection-dir/volt/Health check/.meta.json
new file mode 100644
index 000000000000..66ee7e50cab8
--- /dev/null
+++ b/postman/collection-dir/volt/Health check/.meta.json	
@@ -0,0 +1,5 @@
+{
+  "childrenOrder": [
+    "New Request"
+  ]
+}
diff --git a/postman/collection-dir/volt/Health check/New Request/.event.meta.json b/postman/collection-dir/volt/Health check/New Request/.event.meta.json
new file mode 100644
index 000000000000..688c85746ef1
--- /dev/null
+++ b/postman/collection-dir/volt/Health check/New Request/.event.meta.json	
@@ -0,0 +1,5 @@
+{
+  "eventOrder": [
+    "event.test.js"
+  ]
+}
diff --git a/postman/collection-dir/volt/Health check/New Request/event.test.js b/postman/collection-dir/volt/Health check/New Request/event.test.js
new file mode 100644
index 000000000000..b490b8be090f
--- /dev/null
+++ b/postman/collection-dir/volt/Health check/New Request/event.test.js	
@@ -0,0 +1,4 @@
+// Validate status 2xx
+pm.test("[POST]::/accounts - Status code is 2xx", function () {
+  pm.response.to.be.success;
+});
diff --git a/postman/collection-dir/volt/Health check/New Request/request.json b/postman/collection-dir/volt/Health check/New Request/request.json
new file mode 100644
index 000000000000..4cc8d4b1a966
--- /dev/null
+++ b/postman/collection-dir/volt/Health check/New Request/request.json	
@@ -0,0 +1,20 @@
+{
+  "method": "GET",
+  "header": [
+    {
+      "key": "x-feature",
+      "value": "router-custom",
+      "type": "text",
+      "disabled": true
+    }
+  ],
+  "url": {
+    "raw": "{{baseUrl}}/health",
+    "host": [
+      "{{baseUrl}}"
+    ],
+    "path": [
+      "health"
+    ]
+  }
+}
diff --git a/postman/collection-dir/volt/Health check/New Request/response.json b/postman/collection-dir/volt/Health check/New Request/response.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/postman/collection-dir/volt/Health check/New Request/response.json	
@@ -0,0 +1 @@
+[]
diff --git a/postman/collection-dir/volt/event.prerequest.js b/postman/collection-dir/volt/event.prerequest.js
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/postman/collection-dir/volt/event.test.js b/postman/collection-dir/volt/event.test.js
new file mode 100644
index 000000000000..fb52caec30fc
--- /dev/null
+++ b/postman/collection-dir/volt/event.test.js
@@ -0,0 +1,13 @@
+// Set response object as internal variable
+let jsonData = {};
+try {
+  jsonData = pm.response.json();
+} catch (e) {}
+
+// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
+if (jsonData?.payment_id) {
+  pm.collectionVariables.set("payment_id", jsonData.payment_id);
+  console.log("[LOG]::payment_id - " + jsonData.payment_id);
+}
+
+console.log("[LOG]::x-request-id - " + pm.response.headers.get("x-request-id"));
diff --git a/postman/collection-json/forte.postman_collection.json b/postman/collection-json/forte.postman_collection.json
index cdf381f9f2d5..8297b4778f4a 100644
--- a/postman/collection-json/forte.postman_collection.json
+++ b/postman/collection-json/forte.postman_collection.json
@@ -523,7 +523,7 @@
                       "language": "json"
                     }
                   },
-                  "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4242424242424242\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\",\"last_name\":\"Fix\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\",\"last_name\":\"Fix\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                  "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"routing\":{\"type\":\"single\",\"data\":\"forte\"},\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4242424242424242\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\",\"last_name\":\"Fix\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\",\"last_name\":\"Fix\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                 },
                 "url": {
                   "raw": "{{baseUrl}}/payments",
@@ -646,6 +646,248 @@
         {
           "name": "Happy Cases",
           "item": [
+            {
+              "name": "Scenario7-Create payment with Zero Amount",
+              "item": [
+                {
+                  "name": "Payments - Create",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[POST]::/payments - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[POST]::/payments - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[POST]::/payments - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"processing\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments - Content check if value for 'status' matches 'succeeded'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"succeeded\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "POST",
+                    "header": [
+                      {
+                        "key": "Content-Type",
+                        "value": "application/json"
+                      },
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "body": {
+                      "mode": "raw",
+                      "options": {
+                        "raw": {
+                          "language": "json"
+                        }
+                      },
+                      "raw": "{\"amount\":0,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+65\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"routing\":{\"type\":\"single\",\"data\":\"forte\"},\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4242424242424242\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\",\"last_name\":\"Fix\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\",\"last_name\":\"Fix\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                    },
+                    "url": {
+                      "raw": "{{baseUrl}}/payments",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments"
+                      ]
+                    },
+                    "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+                  },
+                  "response": []
+                },
+                {
+                  "name": "Payments - Retrieve",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[GET]::/payments/:id - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[GET]::/payments/:id - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[GET]::/payments/:id - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"processing\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments/:id - Content check if value for 'status' matches 'succeeded'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"succeeded\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "GET",
+                    "header": [
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "url": {
+                      "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments",
+                        ":id"
+                      ],
+                      "query": [
+                        {
+                          "key": "force_sync",
+                          "value": "true"
+                        }
+                      ],
+                      "variable": [
+                        {
+                          "key": "id",
+                          "value": "{{payment_id}}",
+                          "description": "(Required) unique payment id"
+                        }
+                      ]
+                    },
+                    "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+                  },
+                  "response": []
+                }
+              ]
+            },
             {
               "name": "Scenario1-Create payment with confirm true",
               "item": [
diff --git a/postman/collection-json/multisafepay.postman_collection.json b/postman/collection-json/multisafepay.postman_collection.json
index 8ba70b7c654f..50a2655c5b05 100644
--- a/postman/collection-json/multisafepay.postman_collection.json
+++ b/postman/collection-json/multisafepay.postman_collection.json
@@ -532,7 +532,7 @@
                       "language": "json"
                     }
                   },
-                  "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4242424242424242\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"someone\",\"last_name\":\"happy\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"someone\",\"last_name\":\"happy\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                  "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4242424242424242\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"someone\",\"last_name\":\"happy\"}},\"routing\":{\"type\":\"single\",\"data\":\"multisafepay\"},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"someone\",\"last_name\":\"happy\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                 },
                 "url": {
                   "raw": "{{baseUrl}}/payments",
@@ -1875,6 +1875,233 @@
         {
           "name": "Variation Cases",
           "item": [
+            {
+              "name": "Scenario6- Create payment with Invalid Merchant ID",
+              "item": [
+                {
+                  "name": "Payment Connector - Update",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(",
+                          "  \"[POST]::/account/:account_id/connectors/:connector_id - Status code is 2xx\",",
+                          "  function () {",
+                          "    pm.response.to.be.success;",
+                          "  },",
+                          ");",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(",
+                          "  \"[POST]::/account/:account_id/connectors/:connector_id - Content-Type is application/json\",",
+                          "  function () {",
+                          "    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "      \"application/json\",",
+                          "    );",
+                          "  },",
+                          ");",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set merchant_connector_id as variable for jsonData.merchant_connector_id",
+                          "if (jsonData?.merchant_connector_id) {",
+                          "  pm.collectionVariables.set(",
+                          "    \"merchant_connector_id\",",
+                          "    jsonData.merchant_connector_id,",
+                          "  );",
+                          "  console.log(",
+                          "    \"- use {{merchant_connector_id}} as collection variable for value\",",
+                          "    jsonData.merchant_connector_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{merchant_connector_id}}, as jsonData.merchant_connector_id is undefined.\",",
+                          "  );",
+                          "}",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "auth": {
+                      "type": "apikey",
+                      "apikey": [
+                        {
+                          "key": "value",
+                          "value": "{{admin_api_key}}",
+                          "type": "string"
+                        },
+                        {
+                          "key": "key",
+                          "value": "api-key",
+                          "type": "string"
+                        },
+                        {
+                          "key": "in",
+                          "value": "header",
+                          "type": "string"
+                        }
+                      ]
+                    },
+                    "method": "POST",
+                    "header": [
+                      {
+                        "key": "Content-Type",
+                        "value": "application/json"
+                      },
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "body": {
+                      "mode": "raw",
+                      "options": {
+                        "raw": {
+                          "language": "json"
+                        }
+                      },
+                      "raw": "{\"connector_type\":\"fiz_operations\",\"connector_account_details\":{\"auth_type\":\"HeaderKey\",\"api_key\":\"wrongAPIKey\"},\"test_mode\":false,\"disabled\":false,\"payment_methods_enabled\":[{\"payment_method\":\"card\",\"payment_method_types\":[{\"payment_method_type\":\"credit\",\"card_networks\":[\"Visa\",\"Mastercard\"],\"minimum_amount\":1,\"maximum_amount\":68607706,\"recurring_enabled\":true,\"installment_payment_enabled\":true},{\"payment_method_type\":\"debit\",\"card_networks\":[\"Visa\",\"Mastercard\"],\"minimum_amount\":1,\"maximum_amount\":68607706,\"recurring_enabled\":true,\"installment_payment_enabled\":true}]},{\"payment_method\":\"pay_later\",\"payment_method_types\":[{\"payment_method_type\":\"klarna\",\"payment_experience\":\"redirect_to_url\",\"minimum_amount\":1,\"maximum_amount\":68607706,\"recurring_enabled\":true,\"installment_payment_enabled\":true},{\"payment_method_type\":\"affirm\",\"payment_experience\":\"redirect_to_url\",\"minimum_amount\":1,\"maximum_amount\":68607706,\"recurring_enabled\":true,\"installment_payment_enabled\":true},{\"payment_method_type\":\"afterpay_clearpay\",\"payment_experience\":\"redirect_to_url\",\"minimum_amount\":1,\"maximum_amount\":68607706,\"recurring_enabled\":true,\"installment_payment_enabled\":true}]}],\"metadata\":{\"city\":\"NY\",\"unit\":\"245\"}}"
+                    },
+                    "url": {
+                      "raw": "{{baseUrl}}/account/:account_id/connectors/:connector_id",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "account",
+                        ":account_id",
+                        "connectors",
+                        ":connector_id"
+                      ],
+                      "variable": [
+                        {
+                          "key": "account_id",
+                          "value": "{{merchant_id}}"
+                        },
+                        {
+                          "key": "connector_id",
+                          "value": "{{merchant_connector_id}}"
+                        }
+                      ]
+                    },
+                    "description": "To update an existing Payment Connector. Helpful in enabling / disabling different payment methods and other settings for the connector etc"
+                  },
+                  "response": []
+                },
+                {
+                  "name": "Payments - Create",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[POST]::/payments - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[POST]::/payments - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[POST]::/payments - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// Validate error message in the JSON Body",
+                          "pm.test(\"[POST]::/payments - Validate error message\", function () {",
+                          "  pm.expect(jsonData.error_message).to.not.be.null",
+                          "});",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "POST",
+                    "header": [
+                      {
+                        "key": "Content-Type",
+                        "value": "application/json"
+                      },
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "body": {
+                      "mode": "raw",
+                      "options": {
+                        "raw": {
+                          "language": "json"
+                        }
+                      },
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4242424242424242\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"routing\":{\"type\":\"single\",\"data\":\"multisafepay\"},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"someone\",\"last_name\":\"happy\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"someone\",\"last_name\":\"happy\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                    },
+                    "url": {
+                      "raw": "{{baseUrl}}/payments",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments"
+                      ]
+                    },
+                    "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+                  },
+                  "response": []
+                }
+              ]
+            },
             {
               "name": "Scenario1-Create payment with Invalid card details",
               "item": [
diff --git a/postman/collection-json/paypal.postman_collection.json b/postman/collection-json/paypal.postman_collection.json
index 345695007a8b..4849a27fe051 100644
--- a/postman/collection-json/paypal.postman_collection.json
+++ b/postman/collection-json/paypal.postman_collection.json
@@ -4,7 +4,33 @@
       "listen": "prerequest",
       "script": {
         "exec": [
-          ""
+          "const path = pm.request.url.toString();",
+          "const isPostRequest = pm.request.method.toString() === \"POST\";",
+          "const isPaymentCreation = path.match(/\\/payments$/) && isPostRequest;",
+          "",
+          "if (isPaymentCreation) {",
+          "  try {",
+          "    const request = JSON.parse(pm.request.body.toJSON().raw);",
+          "",
+          "    // Attach routing",
+          "    const routing = { type: \"single\", data: \"paypal\" };",
+          "    request[\"routing\"] = routing;",
+          "",
+          "    let updatedRequest = {",
+          "      mode: \"raw\",",
+          "      raw: JSON.stringify(request),",
+          "      options: {",
+          "        raw: {",
+          "          language: \"json\",",
+          "        },",
+          "      },",
+          "    };",
+          "    pm.request.body.update(updatedRequest);",
+          "  } catch (error) {",
+          "    console.error(\"Failed to inject routing in the request\");",
+          "    console.error(error);",
+          "  }",
+          "}"
         ],
         "type": "text/javascript"
       }
@@ -191,7 +217,7 @@
                       "language": "json"
                     }
                   },
-                  "raw": "{\"merchant_id\":\"merchant_{{$timestamp}}\",\"locker_id\":\"m0010\",\"merchant_name\":\"NewAge Retailer\",\"primary_business_details\":[{\"country\":\"US\",\"business\":\"default\"}],\"merchant_details\":{\"primary_contact_person\":\"John Test\",\"primary_email\":\"JohnTest@test.com\",\"primary_phone\":\"sunt laborum\",\"secondary_contact_person\":\"John Test2\",\"secondary_email\":\"JohnTest2@test.com\",\"secondary_phone\":\"cillum do dolor id\",\"website\":\"www.example.com\",\"about_business\":\"Online Retail with a wide selection of organic products for North America\",\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\"}},\"return_url\":\"https://duck.com\",\"webhook_details\":{\"webhook_version\":\"1.0.1\",\"webhook_username\":\"ekart_retail\",\"webhook_password\":\"password_ekart@123\",\"payment_created_enabled\":true,\"payment_succeeded_enabled\":true,\"payment_failed_enabled\":true},\"sub_merchants_enabled\":false,\"metadata\":{\"city\":\"NY\",\"unit\":\"245\"},\"routing_algorithm\":{\"type\":\"single\",\"data\":\"paypal\"}}"
+                  "raw": "{\"merchant_id\":\"merchant_{{$timestamp}}\",\"locker_id\":\"m0010\",\"merchant_name\":\"NewAge Retailer\",\"primary_business_details\":[{\"country\":\"US\",\"business\":\"default\"}],\"merchant_details\":{\"primary_contact_person\":\"John Test\",\"primary_email\":\"JohnTest@test.com\",\"primary_phone\":\"sunt laborum\",\"secondary_contact_person\":\"John Test2\",\"secondary_email\":\"JohnTest2@test.com\",\"secondary_phone\":\"cillum do dolor id\",\"website\":\"www.example.com\",\"about_business\":\"Online Retail with a wide selection of organic products for North America\",\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\"}},\"return_url\":\"https://duck.com\",\"webhook_details\":{\"webhook_version\":\"1.0.1\",\"webhook_username\":\"ekart_retail\",\"webhook_password\":\"password_ekart@123\",\"payment_created_enabled\":true,\"payment_succeeded_enabled\":true,\"payment_failed_enabled\":true},\"sub_merchants_enabled\":false,\"metadata\":{\"city\":\"NY\",\"unit\":\"245\"}}"
                 },
                 "url": {
                   "raw": "{{baseUrl}}/accounts",
@@ -523,7 +549,7 @@
                       "language": "json"
                     }
                   },
-                  "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                  "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                 },
                 "url": {
                   "raw": "{{baseUrl}}/payments",
@@ -782,7 +808,7 @@
                           "language": "json"
                         }
                       },
-                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":false,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"},\"routing\":{\"type\":\"single\",\"data\":\"paypal\"}}"
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":false,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"},\"routing\":{\"type\":\"single\",\"data\":\"paypal\"}}"
                     },
                     "url": {
                       "raw": "{{baseUrl}}/payments",
@@ -1459,7 +1485,7 @@
                           "language": "json"
                         }
                       },
-                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                     },
                     "url": {
                       "raw": "{{baseUrl}}/payments",
@@ -1751,7 +1777,7 @@
                           "language": "json"
                         }
                       },
-                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":false,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":false,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                     },
                     "url": {
                       "raw": "{{baseUrl}}/payments",
@@ -2389,7 +2415,7 @@
                           "language": "json"
                         }
                       },
-                      "raw": "{\"client_secret\":\"{{client_secret}}\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}}}"
+                      "raw": "{\"client_secret\":\"{{client_secret}}\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}}}"
                     },
                     "url": {
                       "raw": "{{baseUrl}}/payments/:id/confirm",
@@ -2695,7 +2721,7 @@
                           "language": "json"
                         }
                       },
-                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":false,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":false,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                     },
                     "url": {
                       "raw": "{{baseUrl}}/payments",
@@ -3356,7 +3382,7 @@
                           "language": "json"
                         }
                       },
-                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                     },
                     "url": {
                       "raw": "{{baseUrl}}/payments",
@@ -3833,7 +3859,7 @@
                           "language": "json"
                         }
                       },
-                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                     },
                     "url": {
                       "raw": "{{baseUrl}}/payments",
@@ -4310,7 +4336,7 @@
                           "language": "json"
                         }
                       },
-                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                     },
                     "url": {
                       "raw": "{{baseUrl}}/payments",
@@ -5613,7 +5639,7 @@
                           "language": "json"
                         }
                       },
-                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+65\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"13\",\"card_exp_year\":\"2023\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+65\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"13\",\"card_exp_year\":\"2023\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                     },
                     "url": {
                       "raw": "{{baseUrl}}/payments",
@@ -5879,7 +5905,7 @@
                           "language": "json"
                         }
                       },
-                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+65\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"12345\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+65\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"12345\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                     },
                     "url": {
                       "raw": "{{baseUrl}}/payments",
@@ -6340,7 +6366,7 @@
                           "language": "json"
                         }
                       },
-                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                     },
                     "url": {
                       "raw": "{{baseUrl}}/payments",
@@ -6732,7 +6758,7 @@
                           "language": "json"
                         }
                       },
-                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                     },
                     "url": {
                       "raw": "{{baseUrl}}/payments",
@@ -6993,7 +7019,7 @@
                           "language": "json"
                         }
                       },
-                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+65\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4005519200000004\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+65\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"card_number\":\"4012000033330026\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"PiX\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"}}"
                     },
                     "url": {
                       "raw": "{{baseUrl}}/payments",
diff --git a/postman/collection-json/stripe.postman_collection.json b/postman/collection-json/stripe.postman_collection.json
index 136133666c07..5d308dd0fe53 100644
--- a/postman/collection-json/stripe.postman_collection.json
+++ b/postman/collection-json/stripe.postman_collection.json
@@ -81,19 +81,19 @@
       "name": "MerchantAccounts",
       "item": [
         {
-          "name": "Merchant Account - List",
+          "name": "Merchant Account - Create",
           "event": [
             {
               "listen": "test",
               "script": {
                 "exec": [
                   "// Validate status 2xx",
-                  "pm.test(\"[GET]::/accounts/list - Status code is 2xx\", function () {",
+                  "pm.test(\"[POST]::/accounts - Status code is 2xx\", function () {",
                   "  pm.response.to.be.success;",
                   "});",
                   "",
                   "// Validate if response header has matching content-type",
-                  "pm.test(\"[GET]::/accounts/list - Content-Type is application/json\", function () {",
+                  "pm.test(\"[POST]::/accounts - Content-Type is application/json\", function () {",
                   "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
                   "    \"application/json\",",
                   "  );",
@@ -105,6 +105,19 @@
                   "  jsonData = pm.response.json();",
                   "} catch (e) { }",
                   "",
+                  "// pm.collectionVariables - Set merchant_id as variable for jsonData.merchant_id",
+                  "if (jsonData?.merchant_id) {",
+                  "  pm.collectionVariables.set(\"merchant_id\", jsonData.merchant_id);",
+                  "  console.log(",
+                  "    \"- use {{merchant_id}} as collection variable for value\",",
+                  "    jsonData.merchant_id,",
+                  "  );",
+                  "} else {",
+                  "  console.log(",
+                  "    \"INFO - Unable to assign variable {{merchant_id}}, as jsonData.merchant_id is undefined.\",",
+                  "  );",
+                  "}",
+                  "",
                   "// pm.collectionVariables - Set api_key as variable for jsonData.api_key",
                   "if (jsonData?.api_key) {",
                   "  pm.collectionVariables.set(\"api_key\", jsonData.api_key);",
@@ -130,6 +143,36 @@
                   "    \"INFO - Unable to assign variable {{publishable_key}}, as jsonData.publishable_key is undefined.\",",
                   "  );",
                   "}",
+                  "",
+                  "// pm.collectionVariables - Set merchant_id as variable for jsonData.merchant_id",
+                  "if (jsonData?.merchant_id) {",
+                  "  pm.collectionVariables.set(\"organization_id\", jsonData.organization_id);",
+                  "  console.log(",
+                  "    \"- use {{organization_id}} as collection variable for value\",",
+                  "    jsonData.organization_id,",
+                  "  );",
+                  "} else {",
+                  "  console.log(",
+                  "    \"INFO - Unable to assign variable {{organization_id}}, as jsonData.organization_id is undefined.\",",
+                  "  );",
+                  "}",
+                  "",
+                  "// Response body should have \"mandate_id\"",
+                  "pm.test(",
+                  "  \"[POST]::/accounts - Organization id is generated\",",
+                  "  function () {",
+                  "    pm.expect(typeof jsonData.organization_id !== \"undefined\").to.be.true;",
+                  "  },",
+                  ");",
+                  ""
+                ],
+                "type": "text/javascript"
+              }
+            },
+            {
+              "listen": "prerequest",
+              "script": {
+                "exec": [
                   ""
                 ],
                 "type": "text/javascript"
@@ -157,55 +200,53 @@
                 }
               ]
             },
-            "method": "GET",
+            "method": "POST",
             "header": [
+              {
+                "key": "Content-Type",
+                "value": "application/json"
+              },
               {
                 "key": "Accept",
                 "value": "application/json"
               }
             ],
+            "body": {
+              "mode": "raw",
+              "options": {
+                "raw": {
+                  "language": "json"
+                }
+              },
+              "raw": "{\"merchant_id\":\"postman_merchant_GHAction_{{$guid}}\",\"locker_id\":\"m0010\",\"merchant_name\":\"NewAge Retailer\",\"merchant_details\":{\"primary_contact_person\":\"John Test\",\"primary_email\":\"JohnTest@test.com\",\"primary_phone\":\"sunt laborum\",\"secondary_contact_person\":\"John Test2\",\"secondary_email\":\"JohnTest2@test.com\",\"secondary_phone\":\"cillum do dolor id\",\"website\":\"www.example.com\",\"about_business\":\"Online Retail with a wide selection of organic products for North America\",\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\"}},\"return_url\":\"https://duck.com/success\",\"webhook_details\":{\"webhook_version\":\"1.0.1\",\"webhook_username\":\"ekart_retail\",\"webhook_password\":\"password_ekart@123\",\"payment_created_enabled\":true,\"payment_succeeded_enabled\":true,\"payment_failed_enabled\":true},\"sub_merchants_enabled\":false,\"metadata\":{\"city\":\"NY\",\"unit\":\"245\"},\"primary_business_details\":[{\"country\":\"US\",\"business\":\"default\"}]}"
+            },
             "url": {
-              "raw": "{{baseUrl}}/accounts/list",
+              "raw": "{{baseUrl}}/accounts",
               "host": [
                 "{{baseUrl}}"
               ],
               "path": [
-                "accounts",
-                "list"
-              ],
-              "query": [
-                {
-                  "key": "organization_id",
-                  "value": "{{organization_id}}",
-                  "disabled": false
-                }
-              ],
-              "variable": [
-                {
-                  "key": "organization_id",
-                  "value": "{{organization_id}}",
-                  "description": "(Required) - Organization id"
-                }
+                "accounts"
               ]
             },
-            "description": "List merchant accounts for an organization"
+            "description": "Create a new account for a merchant. The merchant could be a seller or retailer or client who likes to receive and send payments."
           },
           "response": []
         },
         {
-          "name": "Merchant Account - Create",
+          "name": "Merchant Account - Retrieve",
           "event": [
             {
               "listen": "test",
               "script": {
                 "exec": [
                   "// Validate status 2xx",
-                  "pm.test(\"[POST]::/accounts - Status code is 2xx\", function () {",
+                  "pm.test(\"[GET]::/accounts/:id - Status code is 2xx\", function () {",
                   "  pm.response.to.be.success;",
                   "});",
                   "",
                   "// Validate if response header has matching content-type",
-                  "pm.test(\"[POST]::/accounts - Content-Type is application/json\", function () {",
+                  "pm.test(\"[GET]::/accounts/:id - Content-Type is application/json\", function () {",
                   "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
                   "    \"application/json\",",
                   "  );",
@@ -215,20 +256,7 @@
                   "let jsonData = {};",
                   "try {",
                   "  jsonData = pm.response.json();",
-                  "} catch (e) { }",
-                  "",
-                  "// pm.collectionVariables - Set merchant_id as variable for jsonData.merchant_id",
-                  "if (jsonData?.merchant_id) {",
-                  "  pm.collectionVariables.set(\"merchant_id\", jsonData.merchant_id);",
-                  "  console.log(",
-                  "    \"- use {{merchant_id}} as collection variable for value\",",
-                  "    jsonData.merchant_id,",
-                  "  );",
-                  "} else {",
-                  "  console.log(",
-                  "    \"INFO - Unable to assign variable {{merchant_id}}, as jsonData.merchant_id is undefined.\",",
-                  "  );",
-                  "}",
+                  "} catch (e) {}",
                   "",
                   "// pm.collectionVariables - Set api_key as variable for jsonData.api_key",
                   "if (jsonData?.api_key) {",
@@ -255,28 +283,6 @@
                   "    \"INFO - Unable to assign variable {{publishable_key}}, as jsonData.publishable_key is undefined.\",",
                   "  );",
                   "}",
-                  "",
-                  "// pm.collectionVariables - Set merchant_id as variable for jsonData.merchant_id",
-                  "if (jsonData?.merchant_id) {",
-                  "  pm.collectionVariables.set(\"organization_id\", jsonData.organization_id);",
-                  "  console.log(",
-                  "    \"- use {{organization_id}} as collection variable for value\",",
-                  "    jsonData.organization_id,",
-                  "  );",
-                  "} else {",
-                  "  console.log(",
-                  "    \"INFO - Unable to assign variable {{organization_id}}, as jsonData.organization_id is undefined.\",",
-                  "  );",
-                  "}",
-                  ""
-                ],
-                "type": "text/javascript"
-              }
-            },
-            {
-              "listen": "prerequest",
-              "script": {
-                "exec": [
                   ""
                 ],
                 "type": "text/javascript"
@@ -304,53 +310,48 @@
                 }
               ]
             },
-            "method": "POST",
+            "method": "GET",
             "header": [
-              {
-                "key": "Content-Type",
-                "value": "application/json"
-              },
               {
                 "key": "Accept",
                 "value": "application/json"
               }
             ],
-            "body": {
-              "mode": "raw",
-              "options": {
-                "raw": {
-                  "language": "json"
-                }
-              },
-              "raw": "{\"merchant_id\":\"postman_merchant_GHAction_{{$guid}}\",\"locker_id\":\"m0010\",\"merchant_name\":\"NewAge Retailer\",\"merchant_details\":{\"primary_contact_person\":\"John Test\",\"primary_email\":\"JohnTest@test.com\",\"primary_phone\":\"sunt laborum\",\"secondary_contact_person\":\"John Test2\",\"secondary_email\":\"JohnTest2@test.com\",\"secondary_phone\":\"cillum do dolor id\",\"website\":\"www.example.com\",\"about_business\":\"Online Retail with a wide selection of organic products for North America\",\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\"}},\"return_url\":\"https://duck.com/success\",\"webhook_details\":{\"webhook_version\":\"1.0.1\",\"webhook_username\":\"ekart_retail\",\"webhook_password\":\"password_ekart@123\",\"payment_created_enabled\":true,\"payment_succeeded_enabled\":true,\"payment_failed_enabled\":true},\"sub_merchants_enabled\":false,\"metadata\":{\"city\":\"NY\",\"unit\":\"245\"},\"primary_business_details\":[{\"country\":\"US\",\"business\":\"default\"}]}"
-            },
             "url": {
-              "raw": "{{baseUrl}}/accounts",
+              "raw": "{{baseUrl}}/accounts/:id",
               "host": [
                 "{{baseUrl}}"
               ],
               "path": [
-                "accounts"
+                "accounts",
+                ":id"
+              ],
+              "variable": [
+                {
+                  "key": "id",
+                  "value": "{{merchant_id}}",
+                  "description": "(Required) The unique identifier for the merchant account"
+                }
               ]
             },
-            "description": "Create a new account for a merchant. The merchant could be a seller or retailer or client who likes to receive and send payments."
+            "description": "Retrieve a merchant account details."
           },
           "response": []
         },
         {
-          "name": "Merchant Account - Retrieve",
+          "name": "Merchant Account - List",
           "event": [
             {
               "listen": "test",
               "script": {
                 "exec": [
                   "// Validate status 2xx",
-                  "pm.test(\"[GET]::/accounts/:id - Status code is 2xx\", function () {",
+                  "pm.test(\"[GET]::/accounts/list - Status code is 2xx\", function () {",
                   "  pm.response.to.be.success;",
                   "});",
                   "",
                   "// Validate if response header has matching content-type",
-                  "pm.test(\"[GET]::/accounts/:id - Content-Type is application/json\", function () {",
+                  "pm.test(\"[GET]::/accounts/list - Content-Type is application/json\", function () {",
                   "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
                   "    \"application/json\",",
                   "  );",
@@ -360,7 +361,7 @@
                   "let jsonData = {};",
                   "try {",
                   "  jsonData = pm.response.json();",
-                  "} catch (e) {}",
+                  "} catch (e) { }",
                   "",
                   "// pm.collectionVariables - Set api_key as variable for jsonData.api_key",
                   "if (jsonData?.api_key) {",
@@ -422,23 +423,30 @@
               }
             ],
             "url": {
-              "raw": "{{baseUrl}}/accounts/:id",
+              "raw": "{{baseUrl}}/accounts/list",
               "host": [
                 "{{baseUrl}}"
               ],
               "path": [
                 "accounts",
-                ":id"
+                "list"
+              ],
+              "query": [
+                {
+                  "key": "organization_id",
+                  "value": "{{organization_id}}",
+                  "disabled": false
+                }
               ],
               "variable": [
                 {
-                  "key": "id",
-                  "value": "{{merchant_id}}",
-                  "description": "(Required) The unique identifier for the merchant account"
+                  "key": "organization_id",
+                  "value": "{{organization_id}}",
+                  "description": "(Required) - Organization id"
                 }
               ]
             },
-            "description": "Retrieve a merchant account details."
+            "description": "List merchant accounts for an organization"
           },
           "response": []
         },
@@ -2646,6 +2654,16 @@
                   "    \"INFO - Unable to assign variable {{refund_id}}, as jsonData.refund_id is undefined.\",",
                   "  );",
                   "}",
+                  "",
+                  "",
+                  "// Response body should have \"profile_id\" and not \"null\"",
+                  "pm.test(",
+                  "  \"[POST]::/payments - Content check if 'profile_id' exists and is not 'null'\",",
+                  "  function () {",
+                  "    pm.expect(typeof jsonData.profile_id !== \"undefined\").to.be.true;",
+                  "    pm.expect(jsonData.profile_id).is.not.null;",
+                  "  },",
+                  ");",
                   ""
                 ],
                 "type": "text/javascript"
@@ -2865,31 +2883,76 @@
           "response": []
         },
         {
-          "name": "Retrieve Customer",
+          "name": "List Customer",
           "event": [
             {
               "listen": "test",
               "script": {
                 "exec": [
                   "// Validate status 2xx",
-                  "pm.test(\"[GET]::/customers/:id - Status code is 2xx\", function () {",
+                  "pm.test(\"[POST]::/customers - Status code is 2xx\", function () {",
                   "  pm.response.to.be.success;",
                   "});",
                   "",
                   "// Validate if response header has matching content-type",
-                  "pm.test(",
-                  "  \"[GET]::/customers/:id - Content-Type is application/json\",",
-                  "  function () {",
-                  "    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
-                  "      \"application/json\",",
-                  "    );",
-                  "  },",
-                  ");",
+                  "pm.test(\"[POST]::/customers - Content-Type is application/json\", function () {",
+                  "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                  "    \"application/json\",",
+                  "  );",
+                  "});",
                   "",
                   "// Validate if response has JSON Body",
-                  "pm.test(\"[GET]::/customers/:id - Response has JSON Body\", function () {",
+                  "pm.test(\"[POST]::/customers - Response has JSON Body\", function () {",
                   "  pm.response.to.have.jsonBody();",
                   "});",
+                  "",
+                  "// Set response object as internal variable",
+                  "let jsonData = {};",
+                  "try {",
+                  "  jsonData = pm.response.json();",
+                  "} catch (e) {}",
+                  "",
+                  "",
+                  "// Response body should have a minimum length of \"1\" for \"customer_id\"",
+                  "if (jsonData?.customer_id) {",
+                  "  pm.test(",
+                  "    \"[POST]::/customers - Content check if value of 'customer_id' has a minimum length of '2'\",",
+                  "    function () {",
+                  "      pm.expect(jsonData.customer_id.length).is.at.least(2);",
+                  "    },",
+                  "  );",
+                  "}",
+                  "",
+                  "",
+                  "// Define the regular expression pattern to match customer_id",
+                  "var customerIdPattern = /^[a-zA-Z0-9_]+$/;",
+                  "",
+                  "// Define an array to store the validation results",
+                  "var validationResults = [];",
+                  "",
+                  "// Iterate through the JSON array",
+                  "jsonData.forEach(function(item, index) {",
+                  "    if (item.hasOwnProperty(\"customer_id\")) {",
+                  "        if (customerIdPattern.test(item.customer_id)) {",
+                  "            validationResults.push(\"customer_id \" + item.customer_id + \" is valid.\");",
+                  "        } else {",
+                  "            validationResults.push(\"customer_id \" + item.customer_id + \" is not valid.\");",
+                  "        }",
+                  "    } else {",
+                  "        validationResults.push(\"customer_id is missing for item at index \" + index);",
+                  "    }",
+                  "});",
+                  "",
+                  "// Check if any customer_id is not valid and fail the test if necessary",
+                  "if (validationResults.some(result => !result.includes(\"is valid\"))) {",
+                  "    pm.test(\"Customer IDs validation failed: \" + validationResults.join(\", \"), function() {",
+                  "        pm.expect(false).to.be.true;",
+                  "    });",
+                  "} else {",
+                  "    pm.test(\"All customer IDs are valid: \" + validationResults.join(\", \"), function() {",
+                  "        pm.expect(true).to.be.true;",
+                  "    });",
+                  "}",
                   ""
                 ],
                 "type": "text/javascript"
@@ -2905,41 +2968,33 @@
               }
             ],
             "url": {
-              "raw": "{{baseUrl}}/customers/:id",
+              "raw": "{{baseUrl}}/customers/list",
               "host": [
                 "{{baseUrl}}"
               ],
               "path": [
                 "customers",
-                ":id"
-              ],
-              "variable": [
-                {
-                  "key": "id",
-                  "value": "{{customer_id}}",
-                  "description": "(Required) unique customer id"
-                }
+                "list"
               ]
-            },
-            "description": "Retrieve a customer's details."
+            }
           },
           "response": []
         },
         {
-          "name": "Update Customer",
+          "name": "Retrieve Customer",
           "event": [
             {
               "listen": "test",
               "script": {
                 "exec": [
                   "// Validate status 2xx",
-                  "pm.test(\"[POST]::/customers/:id - Status code is 2xx\", function () {",
+                  "pm.test(\"[GET]::/customers/:id - Status code is 2xx\", function () {",
                   "  pm.response.to.be.success;",
                   "});",
                   "",
                   "// Validate if response header has matching content-type",
                   "pm.test(",
-                  "  \"[POST]::/customers/:id - Content-Type is application/json\",",
+                  "  \"[GET]::/customers/:id - Content-Type is application/json\",",
                   "  function () {",
                   "    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
                   "      \"application/json\",",
@@ -2948,7 +3003,7 @@
                   ");",
                   "",
                   "// Validate if response has JSON Body",
-                  "pm.test(\"[POST]::/customers/:id - Response has JSON Body\", function () {",
+                  "pm.test(\"[GET]::/customers/:id - Response has JSON Body\", function () {",
                   "  pm.response.to.have.jsonBody();",
                   "});",
                   ""
@@ -2958,18 +3013,79 @@
             }
           ],
           "request": {
-            "method": "POST",
+            "method": "GET",
             "header": [
-              {
-                "key": "Content-Type",
-                "value": "application/json"
-              },
               {
                 "key": "Accept",
                 "value": "application/json"
               }
             ],
-            "body": {
+            "url": {
+              "raw": "{{baseUrl}}/customers/:id",
+              "host": [
+                "{{baseUrl}}"
+              ],
+              "path": [
+                "customers",
+                ":id"
+              ],
+              "variable": [
+                {
+                  "key": "id",
+                  "value": "{{customer_id}}",
+                  "description": "(Required) unique customer id"
+                }
+              ]
+            },
+            "description": "Retrieve a customer's details."
+          },
+          "response": []
+        },
+        {
+          "name": "Update Customer",
+          "event": [
+            {
+              "listen": "test",
+              "script": {
+                "exec": [
+                  "// Validate status 2xx",
+                  "pm.test(\"[POST]::/customers/:id - Status code is 2xx\", function () {",
+                  "  pm.response.to.be.success;",
+                  "});",
+                  "",
+                  "// Validate if response header has matching content-type",
+                  "pm.test(",
+                  "  \"[POST]::/customers/:id - Content-Type is application/json\",",
+                  "  function () {",
+                  "    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                  "      \"application/json\",",
+                  "    );",
+                  "  },",
+                  ");",
+                  "",
+                  "// Validate if response has JSON Body",
+                  "pm.test(\"[POST]::/customers/:id - Response has JSON Body\", function () {",
+                  "  pm.response.to.have.jsonBody();",
+                  "});",
+                  ""
+                ],
+                "type": "text/javascript"
+              }
+            }
+          ],
+          "request": {
+            "method": "POST",
+            "header": [
+              {
+                "key": "Content-Type",
+                "value": "application/json"
+              },
+              {
+                "key": "Accept",
+                "value": "application/json"
+              }
+            ],
+            "body": {
               "mode": "raw",
               "options": {
                 "raw": {
@@ -8253,6 +8369,566 @@
                 }
               ]
             },
+            {
+              "name": "Scenario27-Create a failure card payment with confirm true",
+              "item": [
+                {
+                  "name": "Payments - Create",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[POST]::/payments - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[POST]::/payments - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[POST]::/payments - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"succeeded\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments - Content check if value for 'status' matches 'failed'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"failed\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have \"connector_transaction_id\"",
+                          "pm.test(",
+                          "  \"[POST]::/payments - Content check if 'connector_transaction_id' exists\",",
+                          "  function () {",
+                          "    pm.expect(typeof jsonData.connector_transaction_id !== \"undefined\").to.be",
+                          "      .true;",
+                          "  },",
+                          ");",
+                          "",
+                          "// Response body should have value \"card_declined\" for \"error_code\"",
+                          "if (jsonData?.error_code) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments/:id/confirm - Content check if value for 'error_code' matches 'card_declined'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.error_code).to.eql(\"card_declined\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"message - Your card has insufficient funds., decline_code - insufficient_funds\" for \"error_message\"",
+                          "if (jsonData?.error_message) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments/:id/confirm - Content check if value for 'error_message' matches 'message - Your card has insufficient funds., decline_code - insufficient_funds'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.error_message).to.eql(\"message - Your card has insufficient funds., decline_code - insufficient_funds\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "POST",
+                    "header": [
+                      {
+                        "key": "Content-Type",
+                        "value": "application/json"
+                      },
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "body": {
+                      "mode": "raw",
+                      "options": {
+                        "raw": {
+                          "language": "json"
+                        }
+                      },
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"business_country\":\"US\",\"business_label\":\"default\",\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":1,\"customer_id\":\"bernard123\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+65\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"setup_future_usage\":\"on_session\",\"payment_method\":\"card\",\"payment_method_type\":\"debit\",\"payment_method_data\":{\"card\":{\"card_number\":\"4000000000009995\",\"card_exp_month\":\"01\",\"card_exp_year\":\"24\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"sundari\",\"last_name\":\"sundari\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"sundari\",\"last_name\":\"sundari\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"},\"routing\":{\"type\":\"single\",\"data\":\"stripe\"}}"
+                    },
+                    "url": {
+                      "raw": "{{baseUrl}}/payments",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments"
+                      ]
+                    },
+                    "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+                  },
+                  "response": []
+                },
+                {
+                  "name": "Payments - Retrieve",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[GET]::/payments/:id - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[GET]::/payments/:id - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[GET]::/payments/:id - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"Succeeded\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments/:id - Content check if value for 'status' matches 'failed'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"failed\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have \"connector_transaction_id\"",
+                          "pm.test(",
+                          "  \"[POST]::/payments - Content check if 'connector_transaction_id' exists\",",
+                          "  function () {",
+                          "    pm.expect(typeof jsonData.connector_transaction_id !== \"undefined\").to.be",
+                          "      .true;",
+                          "  },",
+                          ");",
+                          "",
+                          "// Response body should have value \"card_declined\" for \"error_code\"",
+                          "if (jsonData?.error_code) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments/:id/confirm - Content check if value for 'error_code' matches 'card_declined'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.error_code).to.eql(\"card_declined\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"message - Your card has insufficient funds., decline_code - insufficient_funds\" for \"error_message\"",
+                          "if (jsonData?.error_message) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments/:id/confirm - Content check if value for 'error_message' matches 'message - Your card has insufficient funds., decline_code - insufficient_funds'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.error_message).to.eql(\"message - Your card has insufficient funds., decline_code - insufficient_funds\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "GET",
+                    "header": [
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "url": {
+                      "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments",
+                        ":id"
+                      ],
+                      "query": [
+                        {
+                          "key": "force_sync",
+                          "value": "true"
+                        }
+                      ],
+                      "variable": [
+                        {
+                          "key": "id",
+                          "value": "{{payment_id}}",
+                          "description": "(Required) unique payment id"
+                        }
+                      ]
+                    },
+                    "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+                  },
+                  "response": []
+                }
+              ]
+            },
+            {
+              "name": "Scenario27-Create payment without customer_id and with billing address and shipping address",
+              "item": [
+                {
+                  "name": "Payments - Create",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[POST]::/payments - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[POST]::/payments - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[POST]::/payments - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"succeeded\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments - Content check if value for 'status' matches 'succeeded'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"succeeded\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have \"connector_transaction_id\"",
+                          "pm.test(",
+                          "  \"[POST]::/payments - Content check if 'connector_transaction_id' exists\",",
+                          "  function () {",
+                          "    pm.expect(typeof jsonData.connector_transaction_id !== \"undefined\").to.be",
+                          "      .true;",
+                          "  },",
+                          ");",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "POST",
+                    "header": [
+                      {
+                        "key": "Content-Type",
+                        "value": "application/json"
+                      },
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "body": {
+                      "mode": "raw",
+                      "options": {
+                        "raw": {
+                          "language": "json"
+                        }
+                      },
+                      "raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"business_country\":\"US\",\"business_label\":\"default\",\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":1,\"customer_id\":\"bernard123\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+65\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://duck.com\",\"setup_future_usage\":\"on_session\",\"payment_method\":\"card\",\"payment_method_type\":\"debit\",\"payment_method_data\":{\"card\":{\"card_number\":\"4242424242424242\",\"card_exp_month\":\"01\",\"card_exp_year\":\"24\",\"card_holder_name\":\"joseph Doe\",\"card_cvc\":\"123\"}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"sundari\",\"last_name\":\"sundari\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"sundari\",\"last_name\":\"sundari\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"},\"routing\":{\"type\":\"single\",\"data\":\"stripe\"}}"
+                    },
+                    "url": {
+                      "raw": "{{baseUrl}}/payments",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments"
+                      ]
+                    },
+                    "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+                  },
+                  "response": []
+                },
+                {
+                  "name": "Payments - Retrieve",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[GET]::/payments/:id - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[GET]::/payments/:id - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[GET]::/payments/:id - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"Succeeded\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments/:id - Content check if value for 'status' matches 'succeeded'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"succeeded\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have \"connector_transaction_id\"",
+                          "pm.test(",
+                          "  \"[POST]::/payments - Content check if 'connector_transaction_id' exists\",",
+                          "  function () {",
+                          "    pm.expect(typeof jsonData.connector_transaction_id !== \"undefined\").to.be",
+                          "      .true;",
+                          "  },",
+                          ");",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "GET",
+                    "header": [
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "url": {
+                      "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments",
+                        ":id"
+                      ],
+                      "query": [
+                        {
+                          "key": "force_sync",
+                          "value": "true"
+                        }
+                      ],
+                      "variable": [
+                        {
+                          "key": "id",
+                          "value": "{{payment_id}}",
+                          "description": "(Required) unique payment id"
+                        }
+                      ]
+                    },
+                    "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+                  },
+                  "response": []
+                }
+              ]
+            },
             {
               "name": "Scenario1-Create payment with confirm true",
               "item": [
diff --git a/postman/collection-json/volt.postman_collection.json b/postman/collection-json/volt.postman_collection.json
new file mode 100644
index 000000000000..78d4e9d6ea41
--- /dev/null
+++ b/postman/collection-json/volt.postman_collection.json
@@ -0,0 +1,2319 @@
+{
+  "event": [
+    {
+      "listen": "prerequest",
+      "script": {
+        "exec": [
+          ""
+        ],
+        "type": "text/javascript"
+      }
+    },
+    {
+      "listen": "test",
+      "script": {
+        "exec": [
+          "// Set response object as internal variable",
+          "let jsonData = {};",
+          "try {",
+          "  jsonData = pm.response.json();",
+          "} catch (e) {}",
+          "",
+          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+          "if (jsonData?.payment_id) {",
+          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+          "  console.log(\"[LOG]::payment_id - \" + jsonData.payment_id);",
+          "}",
+          "",
+          "console.log(\"[LOG]::x-request-id - \" + pm.response.headers.get(\"x-request-id\"));",
+          ""
+        ],
+        "type": "text/javascript"
+      }
+    }
+  ],
+  "item": [
+    {
+      "name": "Health check",
+      "item": [
+        {
+          "name": "New Request",
+          "event": [
+            {
+              "listen": "test",
+              "script": {
+                "exec": [
+                  "// Validate status 2xx",
+                  "pm.test(\"[POST]::/accounts - Status code is 2xx\", function () {",
+                  "  pm.response.to.be.success;",
+                  "});",
+                  ""
+                ],
+                "type": "text/javascript"
+              }
+            }
+          ],
+          "request": {
+            "method": "GET",
+            "header": [
+              {
+                "key": "x-feature",
+                "value": "router-custom",
+                "type": "text",
+                "disabled": true
+              }
+            ],
+            "url": {
+              "raw": "{{baseUrl}}/health",
+              "host": [
+                "{{baseUrl}}"
+              ],
+              "path": [
+                "health"
+              ]
+            }
+          },
+          "response": []
+        }
+      ]
+    },
+    {
+      "name": "Flow Testcases",
+      "item": [
+        {
+          "name": "QuickStart",
+          "item": [
+            {
+              "name": "Merchant Account - Create",
+              "event": [
+                {
+                  "listen": "test",
+                  "script": {
+                    "exec": [
+                      "// Validate status 2xx",
+                      "pm.test(\"[POST]::/accounts - Status code is 2xx\", function () {",
+                      "  pm.response.to.be.success;",
+                      "});",
+                      "",
+                      "// Validate if response header has matching content-type",
+                      "pm.test(\"[POST]::/accounts - Content-Type is application/json\", function () {",
+                      "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                      "    \"application/json\",",
+                      "  );",
+                      "});",
+                      "",
+                      "// Set response object as internal variable",
+                      "let jsonData = {};",
+                      "try {",
+                      "  jsonData = pm.response.json();",
+                      "} catch (e) {}",
+                      "",
+                      "// pm.collectionVariables - Set merchant_id as variable for jsonData.merchant_id",
+                      "if (jsonData?.merchant_id) {",
+                      "  pm.collectionVariables.set(\"merchant_id\", jsonData.merchant_id);",
+                      "  console.log(",
+                      "    \"- use {{merchant_id}} as collection variable for value\",",
+                      "    jsonData.merchant_id,",
+                      "  );",
+                      "} else {",
+                      "  console.log(",
+                      "    \"INFO - Unable to assign variable {{merchant_id}}, as jsonData.merchant_id is undefined.\",",
+                      "  );",
+                      "}",
+                      "",
+                      "// pm.collectionVariables - Set api_key as variable for jsonData.api_key",
+                      "if (jsonData?.api_key) {",
+                      "  pm.collectionVariables.set(\"api_key\", jsonData.api_key);",
+                      "  console.log(",
+                      "    \"- use {{api_key}} as collection variable for value\",",
+                      "    jsonData.api_key,",
+                      "  );",
+                      "} else {",
+                      "  console.log(",
+                      "    \"INFO - Unable to assign variable {{api_key}}, as jsonData.api_key is undefined.\",",
+                      "  );",
+                      "}",
+                      "",
+                      "// pm.collectionVariables - Set publishable_key as variable for jsonData.publishable_key",
+                      "if (jsonData?.publishable_key) {",
+                      "  pm.collectionVariables.set(\"publishable_key\", jsonData.publishable_key);",
+                      "  console.log(",
+                      "    \"- use {{publishable_key}} as collection variable for value\",",
+                      "    jsonData.publishable_key,",
+                      "  );",
+                      "} else {",
+                      "  console.log(",
+                      "    \"INFO - Unable to assign variable {{publishable_key}}, as jsonData.publishable_key is undefined.\",",
+                      "  );",
+                      "}",
+                      ""
+                    ],
+                    "type": "text/javascript"
+                  }
+                }
+              ],
+              "request": {
+                "auth": {
+                  "type": "apikey",
+                  "apikey": [
+                    {
+                      "key": "value",
+                      "value": "{{admin_api_key}}",
+                      "type": "string"
+                    },
+                    {
+                      "key": "key",
+                      "value": "api-key",
+                      "type": "string"
+                    },
+                    {
+                      "key": "in",
+                      "value": "header",
+                      "type": "string"
+                    }
+                  ]
+                },
+                "method": "POST",
+                "header": [
+                  {
+                    "key": "Content-Type",
+                    "value": "application/json"
+                  },
+                  {
+                    "key": "Accept",
+                    "value": "application/json"
+                  }
+                ],
+                "body": {
+                  "mode": "raw",
+                  "options": {
+                    "raw": {
+                      "language": "json"
+                    }
+                  },
+                  "raw": "{\"merchant_id\":\"postman_merchant_GHAction_{{$guid}}\",\"locker_id\":\"m0010\",\"merchant_name\":\"NewAge Retailer\",\"merchant_details\":{\"primary_contact_person\":\"John Test\",\"primary_email\":\"JohnTest@test.com\",\"primary_phone\":\"sunt laborum\",\"secondary_contact_person\":\"John Test2\",\"secondary_email\":\"JohnTest2@test.com\",\"secondary_phone\":\"cillum do dolor id\",\"website\":\"www.example.com\",\"about_business\":\"Online Retail with a wide selection of organic products for North America\",\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\"}},\"return_url\":\"https://duck.com\",\"webhook_details\":{\"webhook_version\":\"1.0.1\",\"webhook_username\":\"ekart_retail\",\"webhook_password\":\"password_ekart@123\",\"payment_created_enabled\":true,\"payment_succeeded_enabled\":true,\"payment_failed_enabled\":true},\"sub_merchants_enabled\":false,\"metadata\":{\"city\":\"NY\",\"unit\":\"245\"},\"primary_business_details\":[{\"country\":\"US\",\"business\":\"default\"}]}"
+                },
+                "url": {
+                  "raw": "{{baseUrl}}/accounts",
+                  "host": [
+                    "{{baseUrl}}"
+                  ],
+                  "path": [
+                    "accounts"
+                  ]
+                },
+                "description": "Create a new account for a merchant. The merchant could be a seller or retailer or client who likes to receive and send payments."
+              },
+              "response": []
+            },
+            {
+              "name": "API Key - Create",
+              "event": [
+                {
+                  "listen": "test",
+                  "script": {
+                    "exec": [
+                      "// Validate status 2xx",
+                      "pm.test(\"[POST]::/api_keys/:merchant_id - Status code is 2xx\", function () {",
+                      "  pm.response.to.be.success;",
+                      "});",
+                      "",
+                      "// Validate if response header has matching content-type",
+                      "pm.test(",
+                      "  \"[POST]::/api_keys/:merchant_id - Content-Type is application/json\",",
+                      "  function () {",
+                      "    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                      "      \"application/json\",",
+                      "    );",
+                      "  },",
+                      ");",
+                      "",
+                      "// Set response object as internal variable",
+                      "let jsonData = {};",
+                      "try {",
+                      "  jsonData = pm.response.json();",
+                      "} catch (e) {}",
+                      "",
+                      "// pm.collectionVariables - Set api_key_id as variable for jsonData.key_id",
+                      "if (jsonData?.key_id) {",
+                      "  pm.collectionVariables.set(\"api_key_id\", jsonData.key_id);",
+                      "  console.log(",
+                      "    \"- use {{api_key_id}} as collection variable for value\",",
+                      "    jsonData.key_id,",
+                      "  );",
+                      "} else {",
+                      "  console.log(",
+                      "    \"INFO - Unable to assign variable {{api_key_id}}, as jsonData.key_id is undefined.\",",
+                      "  );",
+                      "}",
+                      "",
+                      "// pm.collectionVariables - Set api_key as variable for jsonData.api_key",
+                      "if (jsonData?.api_key) {",
+                      "  pm.collectionVariables.set(\"api_key\", jsonData.api_key);",
+                      "  console.log(",
+                      "    \"- use {{api_key}} as collection variable for value\",",
+                      "    jsonData.api_key,",
+                      "  );",
+                      "} else {",
+                      "  console.log(",
+                      "    \"INFO - Unable to assign variable {{api_key}}, as jsonData.api_key is undefined.\",",
+                      "  );",
+                      "}",
+                      ""
+                    ],
+                    "type": "text/javascript"
+                  }
+                }
+              ],
+              "request": {
+                "auth": {
+                  "type": "apikey",
+                  "apikey": [
+                    {
+                      "key": "value",
+                      "value": "{{admin_api_key}}",
+                      "type": "string"
+                    },
+                    {
+                      "key": "key",
+                      "value": "api-key",
+                      "type": "string"
+                    }
+                  ]
+                },
+                "method": "POST",
+                "header": [
+                  {
+                    "key": "Content-Type",
+                    "value": "application/json"
+                  },
+                  {
+                    "key": "Accept",
+                    "value": "application/json"
+                  }
+                ],
+                "body": {
+                  "mode": "raw",
+                  "raw": "{\"name\":\"API Key 1\",\"description\":null,\"expiration\":\"2099-09-23T01:02:03.000Z\"}"
+                },
+                "url": {
+                  "raw": "{{baseUrl}}/api_keys/:merchant_id",
+                  "host": [
+                    "{{baseUrl}}"
+                  ],
+                  "path": [
+                    "api_keys",
+                    ":merchant_id"
+                  ],
+                  "variable": [
+                    {
+                      "key": "merchant_id",
+                      "value": "{{merchant_id}}"
+                    }
+                  ]
+                }
+              },
+              "response": []
+            },
+            {
+              "name": "Payment Connector - Create",
+              "event": [
+                {
+                  "listen": "test",
+                  "script": {
+                    "exec": [
+                      "// Validate status 2xx",
+                      "pm.test(",
+                      "  \"[POST]::/account/:account_id/connectors - Status code is 2xx\",",
+                      "  function () {",
+                      "    pm.response.to.be.success;",
+                      "  },",
+                      ");",
+                      "",
+                      "// Validate if response header has matching content-type",
+                      "pm.test(",
+                      "  \"[POST]::/account/:account_id/connectors - Content-Type is application/json\",",
+                      "  function () {",
+                      "    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                      "      \"application/json\",",
+                      "    );",
+                      "  },",
+                      ");",
+                      "",
+                      "// Set response object as internal variable",
+                      "let jsonData = {};",
+                      "try {",
+                      "  jsonData = pm.response.json();",
+                      "} catch (e) {}",
+                      "",
+                      "// pm.collectionVariables - Set merchant_connector_id as variable for jsonData.merchant_connector_id",
+                      "if (jsonData?.merchant_connector_id) {",
+                      "  pm.collectionVariables.set(",
+                      "    \"merchant_connector_id\",",
+                      "    jsonData.merchant_connector_id,",
+                      "  );",
+                      "  console.log(",
+                      "    \"- use {{merchant_connector_id}} as collection variable for value\",",
+                      "    jsonData.merchant_connector_id,",
+                      "  );",
+                      "} else {",
+                      "  console.log(",
+                      "    \"INFO - Unable to assign variable {{merchant_connector_id}}, as jsonData.merchant_connector_id is undefined.\",",
+                      "  );",
+                      "}",
+                      ""
+                    ],
+                    "type": "text/javascript"
+                  }
+                }
+              ],
+              "request": {
+                "auth": {
+                  "type": "apikey",
+                  "apikey": [
+                    {
+                      "key": "value",
+                      "value": "{{admin_api_key}}",
+                      "type": "string"
+                    },
+                    {
+                      "key": "key",
+                      "value": "api-key",
+                      "type": "string"
+                    },
+                    {
+                      "key": "in",
+                      "value": "header",
+                      "type": "string"
+                    }
+                  ]
+                },
+                "method": "POST",
+                "header": [
+                  {
+                    "key": "Content-Type",
+                    "value": "application/json"
+                  },
+                  {
+                    "key": "Accept",
+                    "value": "application/json"
+                  }
+                ],
+                "body": {
+                  "mode": "raw",
+                  "options": {
+                    "raw": {
+                      "language": "json"
+                    }
+                  },
+                  "raw": "{\"connector_type\":\"fiz_operations\",\"connector_name\":\"volt\",\"business_country\":\"US\",\"business_label\":\"default\",\"connector_account_details\":{\"auth_type\":\"MultiAuthKey\",\"api_key\":\"{{connector_api_key}}\",\"api_secret\":\"{{connector_api_secret}}\",\"key1\":\"{{connector_key1}}\",\"key2\":\"{{connector_key2}}\"},\"test_mode\":false,\"disabled\":false,\"payment_methods_enabled\":[{\"payment_method\":\"bank_redirect\",\"payment_method_types\":[{\"payment_method_type\":\"open_banking_uk\",\"payment_experience\":null,\"card_networks\":null,\"accepted_currencies\":null,\"accepted_countries\":null,\"minimum_amount\":1,\"maximum_amount\":68607706,\"recurring_enabled\":true,\"installment_payment_enabled\":true}]}]}"
+                },
+                "url": {
+                  "raw": "{{baseUrl}}/account/:account_id/connectors",
+                  "host": [
+                    "{{baseUrl}}"
+                  ],
+                  "path": [
+                    "account",
+                    ":account_id",
+                    "connectors"
+                  ],
+                  "variable": [
+                    {
+                      "key": "account_id",
+                      "value": "{{merchant_id}}",
+                      "description": "(Required) The unique identifier for the merchant account"
+                    }
+                  ]
+                },
+                "description": "Create a new Payment Connector for the merchant account. The connector could be a payment processor / facilitator / acquirer or specialised services like Fraud / Accounting etc."
+              },
+              "response": []
+            },
+            {
+              "name": "Payments - Create",
+              "event": [
+                {
+                  "listen": "test",
+                  "script": {
+                    "exec": [
+                      "// Validate status 2xx",
+                      "pm.test(\"[POST]::/payments - Status code is 2xx\", function () {",
+                      "  pm.response.to.be.success;",
+                      "});",
+                      "",
+                      "// Validate if response header has matching content-type",
+                      "pm.test(\"[POST]::/payments - Content-Type is application/json\", function () {",
+                      "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                      "    \"application/json\",",
+                      "  );",
+                      "});",
+                      "",
+                      "// Validate if response has JSON Body",
+                      "pm.test(\"[POST]::/payments - Response has JSON Body\", function () {",
+                      "  pm.response.to.have.jsonBody();",
+                      "});",
+                      "",
+                      "// Set response object as internal variable",
+                      "let jsonData = {};",
+                      "try {",
+                      "  jsonData = pm.response.json();",
+                      "} catch (e) {}",
+                      "",
+                      "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                      "if (jsonData?.payment_id) {",
+                      "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                      "  console.log(",
+                      "    \"- use {{payment_id}} as collection variable for value\",",
+                      "    jsonData.payment_id,",
+                      "  );",
+                      "} else {",
+                      "  console.log(",
+                      "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                      "  );",
+                      "}",
+                      "",
+                      "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                      "if (jsonData?.mandate_id) {",
+                      "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                      "  console.log(",
+                      "    \"- use {{mandate_id}} as collection variable for value\",",
+                      "    jsonData.mandate_id,",
+                      "  );",
+                      "} else {",
+                      "  console.log(",
+                      "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                      "  );",
+                      "}",
+                      "",
+                      "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                      "if (jsonData?.client_secret) {",
+                      "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                      "  console.log(",
+                      "    \"- use {{client_secret}} as collection variable for value\",",
+                      "    jsonData.client_secret,",
+                      "  );",
+                      "} else {",
+                      "  console.log(",
+                      "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                      "  );",
+                      "}",
+                      ""
+                    ],
+                    "type": "text/javascript"
+                  }
+                }
+              ],
+              "request": {
+                "method": "POST",
+                "header": [
+                  {
+                    "key": "Content-Type",
+                    "value": "application/json"
+                  },
+                  {
+                    "key": "Accept",
+                    "value": "application/json"
+                  }
+                ],
+                "body": {
+                  "mode": "raw",
+                  "options": {
+                    "raw": {
+                      "language": "json"
+                    }
+                  },
+                  "raw": "{\"amount\":6540,\"currency\":\"EUR\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://google.com\",\"payment_method\":\"bank_redirect\",\"payment_method_type\":\"open_banking_uk\",\"payment_method_data\":{\"bank_redirect\":{\"open_banking_uk\":{\"issuer\":\"citi\",\"country\":\"GB\"}}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"joseph\",\"last_name\":\"Doe\"},\"phone\":{\"number\":\"8056594427\",\"country_code\":\"+91\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"joseph\",\"last_name\":\"Doe\"},\"phone\":{\"number\":\"8056594427\",\"country_code\":\"+91\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"},\"routing\":{\"type\":\"single\",\"data\":\"volt\"}}"
+                },
+                "url": {
+                  "raw": "{{baseUrl}}/payments",
+                  "host": [
+                    "{{baseUrl}}"
+                  ],
+                  "path": [
+                    "payments"
+                  ]
+                },
+                "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+              },
+              "response": []
+            },
+            {
+              "name": "Payments - Retrieve",
+              "event": [
+                {
+                  "listen": "test",
+                  "script": {
+                    "exec": [
+                      "// Validate status 2xx",
+                      "pm.test(\"[GET]::/payments/:id - Status code is 2xx\", function () {",
+                      "  pm.response.to.be.success;",
+                      "});",
+                      "",
+                      "// Validate if response header has matching content-type",
+                      "pm.test(\"[GET]::/payments/:id - Content-Type is application/json\", function () {",
+                      "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                      "    \"application/json\",",
+                      "  );",
+                      "});",
+                      "",
+                      "// Set response object as internal variable",
+                      "let jsonData = {};",
+                      "try {",
+                      "  jsonData = pm.response.json();",
+                      "} catch (e) {}",
+                      "",
+                      "// Validate if response has JSON Body",
+                      "pm.test(\"[GET]::/payments/:id - Response has JSON Body\", function () {",
+                      "  pm.response.to.have.jsonBody();",
+                      "});",
+                      "",
+                      "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                      "if (jsonData?.payment_id) {",
+                      "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                      "  console.log(",
+                      "    \"- use {{payment_id}} as collection variable for value\",",
+                      "    jsonData.payment_id,",
+                      "  );",
+                      "} else {",
+                      "  console.log(",
+                      "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                      "  );",
+                      "}",
+                      "",
+                      "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                      "if (jsonData?.mandate_id) {",
+                      "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                      "  console.log(",
+                      "    \"- use {{mandate_id}} as collection variable for value\",",
+                      "    jsonData.mandate_id,",
+                      "  );",
+                      "} else {",
+                      "  console.log(",
+                      "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                      "  );",
+                      "}",
+                      "",
+                      "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                      "if (jsonData?.client_secret) {",
+                      "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                      "  console.log(",
+                      "    \"- use {{client_secret}} as collection variable for value\",",
+                      "    jsonData.client_secret,",
+                      "  );",
+                      "} else {",
+                      "  console.log(",
+                      "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                      "  );",
+                      "}",
+                      ""
+                    ],
+                    "type": "text/javascript"
+                  }
+                }
+              ],
+              "request": {
+                "method": "GET",
+                "header": [
+                  {
+                    "key": "Accept",
+                    "value": "application/json"
+                  }
+                ],
+                "url": {
+                  "raw": "{{baseUrl}}/payments/:id",
+                  "host": [
+                    "{{baseUrl}}"
+                  ],
+                  "path": [
+                    "payments",
+                    ":id"
+                  ],
+                  "variable": [
+                    {
+                      "key": "id",
+                      "value": "{{payment_id}}",
+                      "description": "(Required) unique payment id"
+                    }
+                  ]
+                },
+                "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+              },
+              "response": []
+            }
+          ]
+        },
+        {
+          "name": "Happy Cases",
+          "item": [
+            {
+              "name": "Scenario1-Create payment with confirm true",
+              "item": [
+                {
+                  "name": "Payments - Create",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[POST]::/payments - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[POST]::/payments - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[POST]::/payments - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"requires_customer_action\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments - Content check if value for 'status' matches 'requires_customer_action'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"requires_customer_action\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have \"connector_transaction_id\"",
+                          "pm.test(",
+                          "  \"[POST]::/payments - Content check if 'connector_transaction_id' exists\",",
+                          "  function () {",
+                          "    pm.expect(typeof jsonData.connector_transaction_id !== \"undefined\").to.be",
+                          "      .true;",
+                          "  },",
+                          ");",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "POST",
+                    "header": [
+                      {
+                        "key": "Content-Type",
+                        "value": "application/json"
+                      },
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "body": {
+                      "mode": "raw",
+                      "options": {
+                        "raw": {
+                          "language": "json"
+                        }
+                      },
+                      "raw": "{\"amount\":6540,\"currency\":\"EUR\",\"confirm\":true,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://google.com\",\"payment_method\":\"bank_redirect\",\"payment_method_type\":\"open_banking_uk\",\"payment_method_data\":{\"bank_redirect\":{\"open_banking_uk\":{\"issuer\":\"citi\",\"country\":\"GB\"}}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"joseph\",\"last_name\":\"Doe\"},\"phone\":{\"number\":\"8056594427\",\"country_code\":\"+91\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"joseph\",\"last_name\":\"Doe\"},\"phone\":{\"number\":\"8056594427\",\"country_code\":\"+91\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"},\"routing\":{\"type\":\"single\",\"data\":\"volt\"}}"
+                    },
+                    "url": {
+                      "raw": "{{baseUrl}}/payments",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments"
+                      ]
+                    },
+                    "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+                  },
+                  "response": []
+                },
+                {
+                  "name": "Payments - Retrieve",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[GET]::/payments/:id - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[GET]::/payments/:id - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[GET]::/payments/:id - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"requires_customer_action\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments/:id - Content check if value for 'status' matches 'requires_customer_action'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"requires_customer_action\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have \"connector_transaction_id\"",
+                          "pm.test(",
+                          "  \"[POST]::/payments - Content check if 'connector_transaction_id' exists\",",
+                          "  function () {",
+                          "    pm.expect(typeof jsonData.connector_transaction_id !== \"undefined\").to.be",
+                          "      .true;",
+                          "  },",
+                          ");",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "GET",
+                    "header": [
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "url": {
+                      "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments",
+                        ":id"
+                      ],
+                      "query": [
+                        {
+                          "key": "force_sync",
+                          "value": "true"
+                        }
+                      ],
+                      "variable": [
+                        {
+                          "key": "id",
+                          "value": "{{payment_id}}",
+                          "description": "(Required) unique payment id"
+                        }
+                      ]
+                    },
+                    "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+                  },
+                  "response": []
+                }
+              ]
+            },
+            {
+              "name": "Scenario2-Create payment with confirm false",
+              "item": [
+                {
+                  "name": "Payments - Create",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[POST]::/payments - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[POST]::/payments - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[POST]::/payments - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"requires_confirmation\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments - Content check if value for 'status' matches 'requires_confirmation'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"requires_confirmation\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "POST",
+                    "header": [
+                      {
+                        "key": "Content-Type",
+                        "value": "application/json"
+                      },
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "body": {
+                      "mode": "raw",
+                      "options": {
+                        "raw": {
+                          "language": "json"
+                        }
+                      },
+                      "raw": "{\"amount\":6540,\"currency\":\"EUR\",\"confirm\":false,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://google.com\",\"payment_method\":\"bank_redirect\",\"payment_method_type\":\"open_banking_uk\",\"payment_method_data\":{\"bank_redirect\":{\"open_banking_uk\":{\"issuer\":\"citi\",\"country\":\"GB\"}}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"joseph\",\"last_name\":\"Doe\"},\"phone\":{\"number\":\"8056594427\",\"country_code\":\"+91\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"joseph\",\"last_name\":\"Doe\"},\"phone\":{\"number\":\"8056594427\",\"country_code\":\"+91\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"},\"routing\":{\"type\":\"single\",\"data\":\"volt\"}}"
+                    },
+                    "url": {
+                      "raw": "{{baseUrl}}/payments",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments"
+                      ]
+                    },
+                    "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+                  },
+                  "response": []
+                },
+                {
+                  "name": "Payments - Confirm",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[POST]::/payments/:id/confirm - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(",
+                          "  \"[POST]::/payments/:id/confirm - Content-Type is application/json\",",
+                          "  function () {",
+                          "    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "      \"application/json\",",
+                          "    );",
+                          "  },",
+                          ");",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[POST]::/payments/:id/confirm - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"6540\" for \"amount\"",
+                          "if (jsonData?.amount) {",
+                          "  pm.test(",
+                          "    \"[post]:://payments/:id/capture - Content check if value for 'amount' matches '6540'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.amount).to.eql(6540);",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"6540\" for \"amount_capturable\"",
+                          "if (jsonData?.amount) {",
+                          "  pm.test(",
+                          "    \"[post]:://payments/:id/capture - Content check if value for 'amount_capturable' matches 'amount - 6540'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.amount_capturable).to.eql(6540);",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"requires_customer_action\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments/:id/confirm - Content check if value for 'status' matches 'requires_customer_action'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"requires_customer_action\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have \"connector_transaction_id\"",
+                          "pm.test(",
+                          "  \"[POST]::/payments - Content check if 'connector_transaction_id' exists\",",
+                          "  function () {",
+                          "    pm.expect(typeof jsonData.connector_transaction_id !== \"undefined\").to.be",
+                          "      .true;",
+                          "  },",
+                          ");",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    },
+                    {
+                      "listen": "prerequest",
+                      "script": {
+                        "exec": [
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "auth": {
+                      "type": "apikey",
+                      "apikey": [
+                        {
+                          "key": "value",
+                          "value": "{{publishable_key}}",
+                          "type": "string"
+                        },
+                        {
+                          "key": "key",
+                          "value": "api-key",
+                          "type": "string"
+                        },
+                        {
+                          "key": "in",
+                          "value": "header",
+                          "type": "string"
+                        }
+                      ]
+                    },
+                    "method": "POST",
+                    "header": [
+                      {
+                        "key": "Content-Type",
+                        "value": "application/json"
+                      },
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "body": {
+                      "mode": "raw",
+                      "options": {
+                        "raw": {
+                          "language": "json"
+                        }
+                      },
+                      "raw": "{\"client_secret\":\"{{client_secret}}\"}"
+                    },
+                    "url": {
+                      "raw": "{{baseUrl}}/payments/:id/confirm",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments",
+                        ":id",
+                        "confirm"
+                      ],
+                      "variable": [
+                        {
+                          "key": "id",
+                          "value": "{{payment_id}}",
+                          "description": "(Required) unique payment id"
+                        }
+                      ]
+                    },
+                    "description": "This API is to confirm the payment request and forward payment to the payment processor. This API provides more granular control upon when the API is forwarded to the payment processor. Alternatively you can confirm the payment within the Payments-Create API"
+                  },
+                  "response": []
+                },
+                {
+                  "name": "Payments - Retrieve",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[GET]::/payments/:id - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[GET]::/payments/:id - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[GET]::/payments/:id - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"requires_customer_action\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments:id - Content check if value for 'status' matches 'requires_customer_action'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"requires_customer_action\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"6540\" for \"amount\"",
+                          "if (jsonData?.amount) {",
+                          "  pm.test(",
+                          "    \"[post]:://payments/:id/capture - Content check if value for 'amount' matches '6540'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.amount).to.eql(6540);",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"6540\" for \"amount_capturable\"",
+                          "if (jsonData?.amount) {",
+                          "  pm.test(",
+                          "    \"[post]:://payments/:id/capture - Content check if value for 'amount_capturable' matches 'amount - 6540'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.amount_capturable).to.eql(6540);",
+                          "    },",
+                          "  );",
+                          "}"
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "GET",
+                    "header": [
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "url": {
+                      "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments",
+                        ":id"
+                      ],
+                      "query": [
+                        {
+                          "key": "force_sync",
+                          "value": "true"
+                        }
+                      ],
+                      "variable": [
+                        {
+                          "key": "id",
+                          "value": "{{payment_id}}",
+                          "description": "(Required) unique payment id"
+                        }
+                      ]
+                    },
+                    "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+                  },
+                  "response": []
+                }
+              ]
+            },
+            {
+              "name": "Scenario3-Create payment without PMD",
+              "item": [
+                {
+                  "name": "Payments - Create",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[POST]::/payments - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[POST]::/payments - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[POST]::/payments - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"requires_payment_method\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments - Content check if value for 'status' matches 'requires_payment_method'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"requires_payment_method\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "POST",
+                    "header": [
+                      {
+                        "key": "Content-Type",
+                        "value": "application/json"
+                      },
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "body": {
+                      "mode": "raw",
+                      "options": {
+                        "raw": {
+                          "language": "json"
+                        }
+                      },
+                      "raw": "{\"amount\":6540,\"currency\":\"EUR\",\"confirm\":false,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://google.com\",\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"sundari\",\"last_name\":\"singh\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"sundari\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"},\"routing\":{\"type\":\"single\",\"data\":\"volt\"}}"
+                    },
+                    "url": {
+                      "raw": "{{baseUrl}}/payments",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments"
+                      ]
+                    },
+                    "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+                  },
+                  "response": []
+                },
+                {
+                  "name": "Payments - Confirm",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[POST]::/payments/:id/confirm - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(",
+                          "  \"[POST]::/payments/:id/confirm - Content-Type is application/json\",",
+                          "  function () {",
+                          "    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "      \"application/json\",",
+                          "    );",
+                          "  },",
+                          ");",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[POST]::/payments/:id/confirm - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "// Response body should have value \"requires_customer_action\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments:id/confirm - Content check if value for 'status' matches 'requires_customer_action'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"requires_customer_action\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    },
+                    {
+                      "listen": "prerequest",
+                      "script": {
+                        "exec": [
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "auth": {
+                      "type": "apikey",
+                      "apikey": [
+                        {
+                          "key": "value",
+                          "value": "{{publishable_key}}",
+                          "type": "string"
+                        },
+                        {
+                          "key": "key",
+                          "value": "api-key",
+                          "type": "string"
+                        },
+                        {
+                          "key": "in",
+                          "value": "header",
+                          "type": "string"
+                        }
+                      ]
+                    },
+                    "method": "POST",
+                    "header": [
+                      {
+                        "key": "Content-Type",
+                        "value": "application/json"
+                      },
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "body": {
+                      "mode": "raw",
+                      "options": {
+                        "raw": {
+                          "language": "json"
+                        }
+                      },
+                      "raw": "{\"payment_method\":\"bank_redirect\",\"payment_method_type\":\"open_banking_uk\",\"payment_method_data\":{\"bank_redirect\":{\"open_banking_uk\":{\"issuer\":\"citi\",\"country\":\"GB\"}}},\"client_secret\":\"{{client_secret}}\"}"
+                    },
+                    "url": {
+                      "raw": "{{baseUrl}}/payments/:id/confirm",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments",
+                        ":id",
+                        "confirm"
+                      ],
+                      "variable": [
+                        {
+                          "key": "id",
+                          "value": "{{payment_id}}",
+                          "description": "(Required) unique payment id"
+                        }
+                      ]
+                    },
+                    "description": "This API is to confirm the payment request and forward payment to the payment processor. This API provides more granular control upon when the API is forwarded to the payment processor. Alternatively you can confirm the payment within the Payments-Create API"
+                  },
+                  "response": []
+                },
+                {
+                  "name": "Payments - Retrieve",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[GET]::/payments/:id - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[GET]::/payments/:id - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[GET]::/payments/:id - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"requires_customer_action\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments:id - Content check if value for 'status' matches 'requires_customer_action'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"requires_customer_action\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "GET",
+                    "header": [
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "url": {
+                      "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments",
+                        ":id"
+                      ],
+                      "query": [
+                        {
+                          "key": "force_sync",
+                          "value": "true"
+                        }
+                      ],
+                      "variable": [
+                        {
+                          "key": "id",
+                          "value": "{{payment_id}}",
+                          "description": "(Required) unique payment id"
+                        }
+                      ]
+                    },
+                    "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+                  },
+                  "response": []
+                }
+              ]
+            },
+            {
+              "name": "Scenario4-Bank Redirect-open_banking_uk",
+              "item": [
+                {
+                  "name": "Payments - Create",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[POST]::/payments - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[POST]::/payments - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[POST]::/payments - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"requires_payment_method\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments - Content check if value for 'status' matches 'requires_payment_method'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"requires_payment_method\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "POST",
+                    "header": [
+                      {
+                        "key": "Content-Type",
+                        "value": "application/json"
+                      },
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "body": {
+                      "mode": "raw",
+                      "options": {
+                        "raw": {
+                          "language": "json"
+                        }
+                      },
+                      "raw": "{\"amount\":6540,\"currency\":\"EUR\",\"confirm\":false,\"capture_method\":\"automatic\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"StripeCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+1\",\"description\":\"Its my first payment request\",\"authentication_type\":\"no_three_ds\",\"return_url\":\"https://google.com\",\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"sundari\",\"last_name\":\"singh\"}},\"shipping\":{\"address\":{\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"city\":\"San Fransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"sundari\"}},\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"metadata\":{\"udf1\":\"value1\",\"new_customer\":\"true\",\"login_date\":\"2019-09-10T10:11:12Z\"},\"routing\":{\"type\":\"single\",\"data\":\"volt\"}}"
+                    },
+                    "url": {
+                      "raw": "{{baseUrl}}/payments",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments"
+                      ]
+                    },
+                    "description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
+                  },
+                  "response": []
+                },
+                {
+                  "name": "Payments - Confirm",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[POST]::/payments/:id/confirm - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(",
+                          "  \"[POST]::/payments/:id/confirm - Content-Type is application/json\",",
+                          "  function () {",
+                          "    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "      \"application/json\",",
+                          "    );",
+                          "  },",
+                          ");",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[POST]::/payments/:id/confirm - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"requires_customer_action\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments/:id/confirm - Content check if value for 'status' matches 'requires_customer_action'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"requires_customer_action\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have \"next_action.redirect_to_url\"",
+                          "pm.test(",
+                          "  \"[POST]::/payments - Content check if 'next_action.redirect_to_url' exists\",",
+                          "  function () {",
+                          "    pm.expect(typeof jsonData.next_action.redirect_to_url !== \"undefined\").to.be",
+                          "      .true;",
+                          "  },",
+                          ");",
+                          "",
+                          "// Response body should have value \"open_banking_uk\" for \"payment_method_type\"",
+                          "if (jsonData?.payment_method_type) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments/:id/confirm - Content check if value for 'payment_method_type' matches 'open_banking_uk'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.payment_method_type).to.eql(\"open_banking_uk\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"volt\" for \"connector\"",
+                          "if (jsonData?.connector) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments/:id/confirm - Content check if value for 'connector' matches 'volt'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.connector).to.eql(\"volt\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    },
+                    {
+                      "listen": "prerequest",
+                      "script": {
+                        "exec": [
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "auth": {
+                      "type": "apikey",
+                      "apikey": [
+                        {
+                          "key": "value",
+                          "value": "{{publishable_key}}",
+                          "type": "string"
+                        },
+                        {
+                          "key": "key",
+                          "value": "api-key",
+                          "type": "string"
+                        },
+                        {
+                          "key": "in",
+                          "value": "header",
+                          "type": "string"
+                        }
+                      ]
+                    },
+                    "method": "POST",
+                    "header": [
+                      {
+                        "key": "Content-Type",
+                        "value": "application/json"
+                      },
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "body": {
+                      "mode": "raw",
+                      "options": {
+                        "raw": {
+                          "language": "json"
+                        }
+                      },
+                      "raw": "{\"payment_method\":\"bank_redirect\",\"payment_method_type\":\"open_banking_uk\",\"payment_method_data\":{\"bank_redirect\":{\"open_banking_uk\":{\"issuer\":\"citi\",\"country\":\"GB\"}}},\"client_secret\":\"{{client_secret}}\"}"
+                    },
+                    "url": {
+                      "raw": "{{baseUrl}}/payments/:id/confirm",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments",
+                        ":id",
+                        "confirm"
+                      ],
+                      "variable": [
+                        {
+                          "key": "id",
+                          "value": "{{payment_id}}",
+                          "description": "(Required) unique payment id"
+                        }
+                      ]
+                    },
+                    "description": "This API is to confirm the payment request and forward payment to the payment processor. This API provides more granular control upon when the API is forwarded to the payment processor. Alternatively you can confirm the payment within the Payments-Create API"
+                  },
+                  "response": []
+                },
+                {
+                  "name": "Payments - Retrieve",
+                  "event": [
+                    {
+                      "listen": "test",
+                      "script": {
+                        "exec": [
+                          "// Validate status 2xx",
+                          "pm.test(\"[GET]::/payments/:id - Status code is 2xx\", function () {",
+                          "  pm.response.to.be.success;",
+                          "});",
+                          "",
+                          "// Validate if response header has matching content-type",
+                          "pm.test(\"[GET]::/payments/:id - Content-Type is application/json\", function () {",
+                          "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+                          "    \"application/json\",",
+                          "  );",
+                          "});",
+                          "",
+                          "// Validate if response has JSON Body",
+                          "pm.test(\"[GET]::/payments/:id - Response has JSON Body\", function () {",
+                          "  pm.response.to.have.jsonBody();",
+                          "});",
+                          "",
+                          "// Set response object as internal variable",
+                          "let jsonData = {};",
+                          "try {",
+                          "  jsonData = pm.response.json();",
+                          "} catch (e) {}",
+                          "",
+                          "// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id",
+                          "if (jsonData?.payment_id) {",
+                          "  pm.collectionVariables.set(\"payment_id\", jsonData.payment_id);",
+                          "  console.log(",
+                          "    \"- use {{payment_id}} as collection variable for value\",",
+                          "    jsonData.payment_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id",
+                          "if (jsonData?.mandate_id) {",
+                          "  pm.collectionVariables.set(\"mandate_id\", jsonData.mandate_id);",
+                          "  console.log(",
+                          "    \"- use {{mandate_id}} as collection variable for value\",",
+                          "    jsonData.mandate_id,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret",
+                          "if (jsonData?.client_secret) {",
+                          "  pm.collectionVariables.set(\"client_secret\", jsonData.client_secret);",
+                          "  console.log(",
+                          "    \"- use {{client_secret}} as collection variable for value\",",
+                          "    jsonData.client_secret,",
+                          "  );",
+                          "} else {",
+                          "  console.log(",
+                          "    \"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.\",",
+                          "  );",
+                          "}",
+                          "",
+                          "// Response body should have value \"requires_customer_action\" for \"status\"",
+                          "if (jsonData?.status) {",
+                          "  pm.test(",
+                          "    \"[POST]::/payments:id - Content check if value for 'status' matches 'requires_customer_action'\",",
+                          "    function () {",
+                          "      pm.expect(jsonData.status).to.eql(\"requires_customer_action\");",
+                          "    },",
+                          "  );",
+                          "}",
+                          ""
+                        ],
+                        "type": "text/javascript"
+                      }
+                    }
+                  ],
+                  "request": {
+                    "method": "GET",
+                    "header": [
+                      {
+                        "key": "Accept",
+                        "value": "application/json"
+                      }
+                    ],
+                    "url": {
+                      "raw": "{{baseUrl}}/payments/:id?force_sync=true",
+                      "host": [
+                        "{{baseUrl}}"
+                      ],
+                      "path": [
+                        "payments",
+                        ":id"
+                      ],
+                      "query": [
+                        {
+                          "key": "force_sync",
+                          "value": "true"
+                        }
+                      ],
+                      "variable": [
+                        {
+                          "key": "id",
+                          "value": "{{payment_id}}",
+                          "description": "(Required) unique payment id"
+                        }
+                      ]
+                    },
+                    "description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
+                  },
+                  "response": []
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    }
+  ],
+  "auth": {
+    "type": "apikey",
+    "apikey": [
+      {
+        "key": "value",
+        "value": "{{api_key}}",
+        "type": "string"
+      },
+      {
+        "key": "key",
+        "value": "api-key",
+        "type": "string"
+      },
+      {
+        "key": "in",
+        "value": "header",
+        "type": "string"
+      }
+    ]
+  },
+  "info": {
+    "_postman_id": "ac5a089e-b4a3-43b2-8938-b2e44056e455",
+    "name": "volt",
+    "description": "## Get started\n\nJuspay Router provides a collection of APIs that enable you to process and manage payments. Our APIs accept and return JSON in the HTTP body, and return standard HTTP response codes.  \nYou can consume the APIs directly using your favorite HTTP/REST library.  \nWe have a testing environment referred to \"sandbox\", which you can setup to test API calls without affecting production data.\n\n### Base URLs\n\nUse the following base URLs when making requests to the APIs:\n\n| Environment | Base URL |\n| --- | --- |\n| Sandbox | [https://sandbox.hyperswitch.io](https://sandbox.hyperswitch.io) |\n| Production | [https://router.juspay.io](https://router.juspay.io) |\n\n# Authentication\n\nWhen you sign up for an account, you are given a secret key (also referred as api-key). You may authenticate all API requests with Juspay server by providing the appropriate key in the request Authorization header.  \nNever share your secret api keys. Keep them guarded and secure.\n\nContact Support:  \nName: Juspay Support  \nEmail: [support@juspay.in](mailto:support@juspay.in)",
+    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+    "_exporter_id": "27008363"
+  },
+  "variable": [
+    {
+      "key": "baseUrl",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "admin_api_key",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "api_key",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "merchant_id",
+      "value": ""
+    },
+    {
+      "key": "payment_id",
+      "value": ""
+    },
+    {
+      "key": "customer_id",
+      "value": ""
+    },
+    {
+      "key": "mandate_id",
+      "value": ""
+    },
+    {
+      "key": "payment_method_id",
+      "value": ""
+    },
+    {
+      "key": "refund_id",
+      "value": ""
+    },
+    {
+      "key": "merchant_connector_id",
+      "value": ""
+    },
+    {
+      "key": "client_secret",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "connector_api_key",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "connector_api_secret",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "connector_key1",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "connector_key2",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "publishable_key",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "api_key_id",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "payment_token",
+      "value": ""
+    },
+    {
+      "key": "gateway_merchant_id",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "certificate",
+      "value": "",
+      "type": "string"
+    },
+    {
+      "key": "certificate_keys",
+      "value": "",
+      "type": "string"
+    }
+  ]
+}
diff --git a/scripts/add_connector.sh b/scripts/add_connector.sh
index bcd02f6cbd68..9fdc57bf3c81 100755
--- a/scripts/add_connector.sh
+++ b/scripts/add_connector.sh
@@ -6,7 +6,7 @@ function find_prev_connector() {
     git checkout $self
     cp $self $self.tmp
     # Add new connector to existing list and sort it
-    connectors=(aci adyen airwallex applepay authorizedotnet bambora bitpay bluesnap boku braintree cashtocode checkout coinbase cryptopay cybersource dlocal dummyconnector fiserv forte globalpay globepay gocardless helcim iatapay klarna mollie multisafepay nexinets noon nuvei opayo opennode payeezy payme paypal payu powertranz prophetpay rapyd shift4 square stax stripe trustpay tsys volt wise worldline worldpay "$1")
+    connectors=(aci adyen airwallex applepay authorizedotnet bambora bankofamerica bitpay bluesnap boku braintree cashtocode checkout coinbase cryptopay cybersource dlocal dummyconnector fiserv forte globalpay globepay gocardless helcim iatapay klarna mollie multisafepay nexinets noon nuvei opayo opennode payeezy payme paypal payu powertranz prophetpay rapyd shift4 square stax stripe trustpay tsys volt wise worldline worldpay "$1")
     IFS=$'\n' sorted=($(sort <<<"${connectors[*]}")); unset IFS
     res=`echo ${sorted[@]}`
     sed -i'' -e "s/^    connectors=.*/    connectors=($res \"\$1\")/" $self.tmp