diff --git a/.github/workflows/pyatlan-pr.yaml b/.github/workflows/pyatlan-pr.yaml
index b77cf1207..9d916e62f 100644
--- a/.github/workflows/pyatlan-pr.yaml
+++ b/.github/workflows/pyatlan-pr.yaml
@@ -56,7 +56,7 @@ jobs:
 
       - name: Install dependencies
         run: |
-          python -m pip install --no-cache-dir --upgrade pip
+          python -m pip install --no-cache-dir --upgrade pip setuptools
           if [ -f requirements.txt ]; then pip install --no-cache-dir -r requirements.txt; fi
           if [ -f requirements-dev.txt ]; then pip install --no-cache-dir -r requirements-dev.txt; fi
 
@@ -102,7 +102,7 @@ jobs:
 
       - name: Install dependencies
         run: |
-          python -m pip install --no-cache-dir --upgrade pip
+          python -m pip install --no-cache-dir --upgrade pip setuptools
           if [ -f requirements.txt ]; then pip install --no-cache-dir -r requirements.txt; fi
           if [ -f requirements-dev.txt ]; then pip install --no-cache-dir -r requirements-dev.txt; fi
 
diff --git a/pyatlan/errors.py b/pyatlan/errors.py
index edb45efec..8dadf1d9d 100644
--- a/pyatlan/errors.py
+++ b/pyatlan/errors.py
@@ -51,6 +51,17 @@ def __str__(self):
         )
 
 
+class DependencyNotFoundError(Exception):
+    """
+    Raised when a required external dependency is not installed.
+
+    This exception is typically used to indicate that an optional library
+    or plugin needed for a specific feature is missing.
+    """
+
+    pass
+
+
 class ApiConnectionError(AtlanError):
     """Error that occurs when there is an intermittent issue with the API, such as a network outage or an inability
     to connect due to an incorrect URL."""
diff --git a/pyatlan/test_utils/__init__.py b/pyatlan/test_utils/__init__.py
index e2a1ec59d..b82aec9f9 100644
--- a/pyatlan/test_utils/__init__.py
+++ b/pyatlan/test_utils/__init__.py
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: Apache-2.0
-# Copyright 2024 Atlan Pte. Ltd.
+# Copyright 2025 Atlan Pte. Ltd.
 import logging
 import random
 from os import path
diff --git a/pyatlan/test_utils/base_vcr.py b/pyatlan/test_utils/base_vcr.py
new file mode 100644
index 000000000..1930b346b
--- /dev/null
+++ b/pyatlan/test_utils/base_vcr.py
@@ -0,0 +1,294 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright 2025 Atlan Pte. Ltd.
+
+import pkg_resources  # type: ignore[import-untyped]
+
+from pyatlan.errors import DependencyNotFoundError
+
+# Check if pytest-vcr plugin is installed
+try:
+    pkg_resources.get_distribution("pytest-vcr")
+except pkg_resources.DistributionNotFound:
+    raise DependencyNotFoundError(
+        "pytest-vcr plugin is not installed. Please install pytest-vcr."
+    )
+
+# Check if vcrpy is installed and ensure the version is 6.0.x
+try:
+    vcr_version = pkg_resources.get_distribution("vcrpy").version
+    if not vcr_version.startswith("6.0"):
+        raise DependencyNotFoundError(
+            f"vcrpy version 6.0.x is required, but found {vcr_version}. Please install the correct version."
+        )
+except pkg_resources.DistributionNotFound:
+    raise DependencyNotFoundError(
+        "vcrpy version 6.0.x is not installed. Please install vcrpy version 6.0.x."
+    )
+
+import json
+import os
+from typing import Any, Dict, Union
+
+import pytest
+import yaml  # type: ignore[import-untyped]
+
+
+class LiteralBlockScalar(str):
+    """Formats the string as a literal block scalar, preserving whitespace and
+    without interpreting escape characters"""
+
+
+def literal_block_scalar_presenter(dumper, data):
+    """Represents a scalar string as a literal block, via '|' syntax"""
+    return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|")
+
+
+yaml.add_representer(LiteralBlockScalar, literal_block_scalar_presenter)
+
+
+def process_string_value(string_value):
+    """Pretty-prints JSON or returns long strings as a LiteralBlockScalar"""
+    try:
+        json_data = json.loads(string_value)
+        return LiteralBlockScalar(json.dumps(json_data, indent=2))
+    except (ValueError, TypeError):
+        if len(string_value) > 80:
+            return LiteralBlockScalar(string_value)
+    return string_value
+
+
+def convert_body_to_literal(data):
+    """Searches the data for body strings, attempting to pretty-print JSON"""
+    if isinstance(data, dict):
+        for key, value in data.items():
+            # Handle response body case (e.g: response.body.string)
+            if key == "body" and isinstance(value, dict) and "string" in value:
+                value["string"] = process_string_value(value["string"])
+
+            # Handle request body case (e.g: request.body)
+            elif key == "body" and isinstance(value, str):
+                data[key] = process_string_value(value)
+
+            else:
+                convert_body_to_literal(value)
+
+    elif isinstance(data, list):
+        for idx, choice in enumerate(data):
+            data[idx] = convert_body_to_literal(choice)
+
+    return data
+
+
+class VCRPrettyPrintYamlJSONBody:
+    """This makes request and response YAML JSON body recordings more readable."""
+
+    @staticmethod
+    def serialize(cassette_dict):
+        cassette_dict = convert_body_to_literal(cassette_dict)
+        return yaml.dump(cassette_dict, default_flow_style=False, allow_unicode=True)
+
+    @staticmethod
+    def deserialize(cassette_string):
+        return yaml.safe_load(cassette_string)
+
+
+class VCRPrettyPrintJSONBody:
+    """Makes request and response JSON body recordings more readable."""
+
+    @staticmethod
+    def _parse_json_body(
+        body: Union[str, bytes, None],
+    ) -> Union[Dict[str, Any], str, None, bytes]:
+        """Parse JSON body if possible, otherwise return the original body."""
+        if body is None:
+            return None
+
+        # Convert bytes to string if needed
+        if isinstance(body, bytes):
+            try:
+                body = body.decode("utf-8")
+            except UnicodeDecodeError:
+                return body  # Return original if can't decode
+
+        # If it's a string, try to parse as JSON
+        if isinstance(body, str):
+            try:
+                return json.loads(body)
+            except json.JSONDecodeError:
+                return body  # Return original if not valid JSON
+
+        return body  # Return original for other types
+
+    @staticmethod
+    def serialize(cassette_dict: dict) -> str:
+        """
+        Converts body strings to parsed JSON objects for better readability when possible.
+        """
+        # Safety check for cassette_dict
+        if not cassette_dict or not isinstance(cassette_dict, dict):
+            cassette_dict = {}
+
+        interactions = cassette_dict.get("interactions", []) or []
+
+        for interaction in interactions:
+            if not interaction:
+                continue
+
+            # Handle response body
+            response = interaction.get("response") or {}
+            body_container = response.get("body")
+            if isinstance(body_container, dict) and "string" in body_container:
+                parsed_body = VCRPrettyPrintJSONBody._parse_json_body(
+                    body_container["string"]
+                )
+                if isinstance(parsed_body, dict):
+                    # Replace string field with parsed_json field
+                    response["body"] = {"parsed_json": parsed_body}
+
+            # Handle request body
+            request = interaction.get("request") or {}
+            body_container = request.get("body")
+            if isinstance(body_container, dict) and "string" in body_container:
+                parsed_body = VCRPrettyPrintJSONBody._parse_json_body(
+                    body_container["string"]
+                )
+                if isinstance(parsed_body, dict):
+                    # Replace string field with parsed_json field
+                    request["body"] = {"parsed_json": parsed_body}
+
+        # Serialize the final dictionary into a JSON string with pretty formatting
+        try:
+            return json.dumps(cassette_dict, indent=2, ensure_ascii=False) + "\n"
+        except TypeError as exc:
+            raise TypeError(
+                "Does this HTTP interaction contain binary data? "
+                "If so, use a different serializer (like the YAML serializer)."
+            ) from exc
+
+    @staticmethod
+    def deserialize(cassette_string: str) -> dict:
+        """
+        Deserializes a JSON string into a dictionary and converts
+        parsed_json fields back to string fields.
+        """
+        # Safety check for cassette_string
+        if not cassette_string:
+            return {}
+
+        try:
+            cassette_dict = json.loads(cassette_string)
+        except json.JSONDecodeError:
+            return {}
+
+        # Convert parsed_json back to string format
+        interactions = cassette_dict.get("interactions", []) or []
+
+        for interaction in interactions:
+            if not interaction:
+                continue
+
+            # Handle response body
+            response = interaction.get("response") or {}
+            body_container = response.get("body")
+            if isinstance(body_container, dict) and "parsed_json" in body_container:
+                json_body = body_container["parsed_json"]
+                response["body"] = {"string": json.dumps(json_body)}
+
+            # Handle request body
+            request = interaction.get("request") or {}
+            body_container = request.get("body")
+            if isinstance(body_container, dict) and "parsed_json" in body_container:
+                json_body = body_container["parsed_json"]
+                request["body"] = {"string": json.dumps(json_body)}
+
+        return cassette_dict
+
+
+class BaseVCR:
+    """
+    A base class for configuring VCR (Virtual Cassette Recorder)
+    for HTTP request/response recording and replaying.
+
+    This class provides pytest fixtures to set up the VCR configuration
+    and custom serializers for JSON and YAML formats.
+    It also handles cassette directory configuration.
+    """
+
+    class VCRRemoveAllHeaders:
+        """
+        A class responsible for removing all headers from requests and responses.
+        This can be useful for scenarios where headers are not needed for matching or comparison
+        in VCR (Virtual Cassette Recorder) interactions, such as when recording or replaying HTTP requests.
+        """
+
+        @staticmethod
+        def remove_all_request_headers(request):
+            # Save only what's necessary for matching
+            request.headers = {}
+            return request
+
+        @staticmethod
+        def remove_all_response_headers(response):
+            # Save only what's necessary for matching
+            response["headers"] = {}
+            return response
+
+    _CASSETTES_DIR = None
+    _BASE_CONFIG = {
+        # More config options can be found at:
+        # https://vcrpy.readthedocs.io/en/latest/configuration.html#configuration
+        "record_mode": "once",  # (default: "once", "always", "none", "new_episodes")
+        "serializer": "pretty-yaml",  # (default: "yaml")
+        "decode_compressed_response": True,  # Decode compressed responses
+        # (optional) Replace the Authorization request header with "**REDACTED**" in cassettes
+        # "filter_headers": [("authorization", "**REDACTED**")],
+        "before_record_request": VCRRemoveAllHeaders.remove_all_request_headers,
+        "before_record_response": VCRRemoveAllHeaders.remove_all_response_headers,
+    }
+
+    @pytest.fixture(scope="module")
+    def vcr(self, vcr):
+        """
+        Registers custom serializers for VCR and returns the VCR instance.
+
+        The method registers two custom serializers:
+        - "pretty-json" for pretty-printing JSON responses.
+        - "pretty-yaml" for pretty-printing YAML responses.
+
+        :param vcr: The VCR instance provided by the pytest-vcr plugin
+        :returns: modified VCR instance with custom serializers registered
+        """
+        vcr.register_serializer("pretty-json", VCRPrettyPrintJSONBody)
+        vcr.register_serializer("pretty-yaml", VCRPrettyPrintYamlJSONBody)
+        return vcr
+
+    @pytest.fixture(scope="module")
+    def vcr_config(self):
+        """
+        Provides the VCR configuration dictionary.
+
+        The configuration includes default options for the recording mode,
+        serializer, response decoding, and filtering headers.
+        This configuration is used to set up VCR behavior during tests.
+
+        :returns: a dictionary with VCR configuration options
+        """
+        return self._BASE_CONFIG
+
+    @pytest.fixture(scope="module")
+    def vcr_cassette_dir(self, request):
+        """
+        Provides the directory path for storing VCR cassettes.
+
+        If a custom cassette directory is set in the class, it is used;
+        otherwise, the default directory structure is created under "tests/cassettes".
+        The directory path will be based on the module name.
+
+        :param request: request object which provides metadata about the test
+
+        :returns: directory path for storing cassettes
+        """
+        # Set self._CASSETTES_DIR or use the default directory path based on the test module name
+        return self._CASSETTES_DIR or os.path.join(
+            "tests/vcr_cassettes", request.module.__name__
+        )
diff --git a/requirements-dev.txt b/requirements-dev.txt
index dec693508..3d25f0c2c 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,7 +1,14 @@
 mypy~=1.9.0
 ruff~=0.9.9
-types-requests~=2.32.0.20241016
+# [PINNED] for Python 3.8 compatibility
+# higher versions require urllib3>=2.0
+types-requests~=2.31.0.6
+types-setuptools~=75.8.0.20250110
 pytest~=8.3.4
+pytest-vcr~=1.0.2
+# [PINNED] to v6.x since vcrpy>=7.0 requires urllib3>=2.0
+# which breaks compatibility with Python 3.8
+vcrpy~=6.0.2
 pytest-order~=1.3.0
 pytest-timer[termcolor]~=1.0.0
 pytest-sugar~=1.0.0
diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py
index a4a71b48e..ee8142e0e 100644
--- a/tests/unit/conftest.py
+++ b/tests/unit/conftest.py
@@ -31,3 +31,19 @@ def mock_custom_metadata_cache():
 def mock_tag_cache():
     with patch("pyatlan.cache.atlan_tag_cache.AtlanTagCache") as cache:
         yield cache
+
+
+@pytest.fixture(autouse=True)
+def patch_vcr_http_response_version_string():
+    """
+    Patch the VCRHTTPResponse class to add a version_string attribute if it doesn't exist.
+
+    This patch is necessary to avoid bumping vcrpy to 7.0.0,
+    which drops support for Python 3.8.
+    """
+    from vcr.stubs import VCRHTTPResponse  # type: ignore[import-untyped]
+
+    if not hasattr(VCRHTTPResponse, "version_string"):
+        VCRHTTPResponse.version_string = None
+
+    yield
diff --git a/tests/unit/test_base_vcr_json.py b/tests/unit/test_base_vcr_json.py
new file mode 100644
index 000000000..32f79a673
--- /dev/null
+++ b/tests/unit/test_base_vcr_json.py
@@ -0,0 +1,65 @@
+import pytest
+import requests
+
+from pyatlan.test_utils.base_vcr import BaseVCR
+
+
+class TestBaseVCRJSON(BaseVCR):
+    """
+    Integration tests to demonstrate VCR.py capabilities
+    by recording and replaying HTTP interactions using
+    HTTPBin (https://httpbin.org) for GET, POST, PUT, and DELETE requests.
+    """
+
+    BASE_URL = "https://httpbin.org"
+
+    @pytest.fixture(scope="session")
+    def vcr_config(self):
+        """
+        Override the VCR configuration to use JSON serialization across the module.
+        """
+        config = self._BASE_CONFIG.copy()
+        config.update({"serializer": "pretty-json"})
+        return config
+
+    @pytest.mark.vcr()
+    def test_httpbin_get(self):
+        """
+        Test a simple GET request to httpbin.
+        """
+        url = f"{self.BASE_URL}/get"
+        response = requests.get(url, params={"test": "value"})
+        assert response.status_code == 200
+        assert response.json()["args"]["test"] == "value"
+
+    @pytest.mark.vcr()
+    def test_httpbin_post(self):
+        """
+        Test a simple POST request to httpbin.
+        """
+        url = f"{self.BASE_URL}/post"
+        payload = {"name": "atlan", "type": "integration-test"}
+        response = requests.post(url, json=payload)
+        assert response.status_code == 200
+        assert response.json()["json"] == payload
+
+    @pytest.mark.vcr()
+    def test_httpbin_put(self):
+        """
+        Test a simple PUT request to httpbin.
+        """
+        url = f"{self.BASE_URL}/put"
+        payload = {"update": "value"}
+        response = requests.put(url, json=payload)
+        assert response.status_code == 200
+        assert response.json()["json"] == payload
+
+    @pytest.mark.vcr()
+    def test_httpbin_delete(self):
+        """
+        Test a simple DELETE request to httpbin.
+        """
+        url = f"{self.BASE_URL}/delete"
+        response = requests.delete(url)
+        assert response.status_code == 200
+        assert response.json()["args"] == {}
diff --git a/tests/unit/test_base_vcr_yaml.py b/tests/unit/test_base_vcr_yaml.py
new file mode 100644
index 000000000..107f9f351
--- /dev/null
+++ b/tests/unit/test_base_vcr_yaml.py
@@ -0,0 +1,61 @@
+import pytest
+import requests
+
+from pyatlan.test_utils.base_vcr import BaseVCR
+
+
+class TestBaseVCRYAML(BaseVCR):
+    """
+    Integration tests to demonstrate VCR.py capabilities
+    by recording and replaying HTTP interactions using
+    HTTPBin (https://httpbin.org) for GET, POST, PUT, and DELETE requests.
+    """
+
+    BASE_URL = "https://httpbin.org"
+
+    @pytest.mark.vcr()
+    def test_httpbin_get(self):
+        """
+        Test a simple GET request to httpbin.
+        """
+        url = f"{self.BASE_URL}/get"
+        response = requests.get(url, params={"test": "value"})
+
+        assert response.status_code == 200
+        assert response.json()["args"]["test"] == "value"
+
+    @pytest.mark.vcr()
+    def test_httpbin_post(self):
+        """
+        Test a simple POST request to httpbin.
+        """
+        url = f"{self.BASE_URL}/post"
+        payload = {"name": "atlan", "type": "integration-test"}
+        response = requests.post(url, json=payload)
+
+        assert response.status_code == 200
+        assert response.json()["json"] == payload
+
+    @pytest.mark.vcr()
+    def test_httpbin_put(self):
+        """
+        Test a simple PUT request to httpbin.
+        """
+        url = f"{self.BASE_URL}/put"
+        payload = {"update": "value"}
+        response = requests.put(url, json=payload)
+
+        assert response.status_code == 200
+        assert response.json()["json"] == payload
+
+    @pytest.mark.vcr()
+    def test_httpbin_delete(self):
+        """
+        Test a simple DELETE request to httpbin.
+        """
+        url = f"{self.BASE_URL}/delete"
+        response = requests.delete(url)
+
+        assert response.status_code == 200
+        # HTTPBin returns an empty JSON object for DELETE
+        assert response.json()["args"] == {}
diff --git a/tests/vcr_cassettes/tests.unit.test_base_vcr_json/TestBaseVCRJSON.test_httpbin_delete.yaml b/tests/vcr_cassettes/tests.unit.test_base_vcr_json/TestBaseVCRJSON.test_httpbin_delete.yaml
new file mode 100644
index 000000000..bd2cb4d96
--- /dev/null
+++ b/tests/vcr_cassettes/tests.unit.test_base_vcr_json/TestBaseVCRJSON.test_httpbin_delete.yaml
@@ -0,0 +1,39 @@
+{
+  "version": 1,
+  "interactions": [
+    {
+      "request": {
+        "method": "DELETE",
+        "uri": "https://httpbin.org/delete",
+        "body": null,
+        "headers": {}
+      },
+      "response": {
+        "status": {
+          "code": 200,
+          "message": "OK"
+        },
+        "headers": {},
+        "body": {
+          "parsed_json": {
+            "args": {},
+            "data": "",
+            "files": {},
+            "form": {},
+            "headers": {
+              "Accept": "*/*",
+              "Accept-Encoding": "gzip, deflate",
+              "Content-Length": "0",
+              "Host": "httpbin.org",
+              "User-Agent": "python-requests/2.32.3",
+              "X-Amzn-Trace-Id": "Root=1-680f7263-439ec4f97dc37ffe07c63697"
+            },
+            "json": null,
+            "origin": "x.x.x.x",
+            "url": "https://httpbin.org/delete"
+          }
+        }
+      }
+    }
+  ]
+}
diff --git a/tests/vcr_cassettes/tests.unit.test_base_vcr_json/TestBaseVCRJSON.test_httpbin_get.yaml b/tests/vcr_cassettes/tests.unit.test_base_vcr_json/TestBaseVCRJSON.test_httpbin_get.yaml
new file mode 100644
index 000000000..ed2c14dcf
--- /dev/null
+++ b/tests/vcr_cassettes/tests.unit.test_base_vcr_json/TestBaseVCRJSON.test_httpbin_get.yaml
@@ -0,0 +1,36 @@
+{
+  "version": 1,
+  "interactions": [
+    {
+      "request": {
+        "method": "GET",
+        "uri": "https://httpbin.org/get?test=value",
+        "body": null,
+        "headers": {}
+      },
+      "response": {
+        "status": {
+          "code": 200,
+          "message": "OK"
+        },
+        "headers": {},
+        "body": {
+          "parsed_json": {
+            "args": {
+              "test": "value"
+            },
+            "headers": {
+              "Accept": "*/*",
+              "Accept-Encoding": "gzip, deflate",
+              "Host": "httpbin.org",
+              "User-Agent": "python-requests/2.32.3",
+              "X-Amzn-Trace-Id": "Root=1-680f7259-4e5c927e25a0aa78202e04e1"
+            },
+            "origin": "x.x.x.x",
+            "url": "https://httpbin.org/get?test=value"
+          }
+        }
+      }
+    }
+  ]
+}
diff --git a/tests/vcr_cassettes/tests.unit.test_base_vcr_json/TestBaseVCRJSON.test_httpbin_post.yaml b/tests/vcr_cassettes/tests.unit.test_base_vcr_json/TestBaseVCRJSON.test_httpbin_post.yaml
new file mode 100644
index 000000000..2d245a440
--- /dev/null
+++ b/tests/vcr_cassettes/tests.unit.test_base_vcr_json/TestBaseVCRJSON.test_httpbin_post.yaml
@@ -0,0 +1,43 @@
+{
+  "version": 1,
+  "interactions": [
+    {
+      "request": {
+        "method": "POST",
+        "uri": "https://httpbin.org/post",
+        "body": "{\"name\": \"atlan\", \"type\": \"integration-test\"}",
+        "headers": {}
+      },
+      "response": {
+        "status": {
+          "code": 200,
+          "message": "OK"
+        },
+        "headers": {},
+        "body": {
+          "parsed_json": {
+            "args": {},
+            "data": "{\"name\": \"atlan\", \"type\": \"integration-test\"}",
+            "files": {},
+            "form": {},
+            "headers": {
+              "Accept": "*/*",
+              "Accept-Encoding": "gzip, deflate",
+              "Content-Length": "45",
+              "Content-Type": "application/json",
+              "Host": "httpbin.org",
+              "User-Agent": "python-requests/2.32.3",
+              "X-Amzn-Trace-Id": "Root=1-680f725c-53119e7d4121a80069c14836"
+            },
+            "json": {
+              "name": "atlan",
+              "type": "integration-test"
+            },
+            "origin": "x.x.x.x",
+            "url": "https://httpbin.org/post"
+          }
+        }
+      }
+    }
+  ]
+}
diff --git a/tests/vcr_cassettes/tests.unit.test_base_vcr_json/TestBaseVCRJSON.test_httpbin_put.yaml b/tests/vcr_cassettes/tests.unit.test_base_vcr_json/TestBaseVCRJSON.test_httpbin_put.yaml
new file mode 100644
index 000000000..a5872a1b6
--- /dev/null
+++ b/tests/vcr_cassettes/tests.unit.test_base_vcr_json/TestBaseVCRJSON.test_httpbin_put.yaml
@@ -0,0 +1,42 @@
+{
+  "version": 1,
+  "interactions": [
+    {
+      "request": {
+        "method": "PUT",
+        "uri": "https://httpbin.org/put",
+        "body": "{\"update\": \"value\"}",
+        "headers": {}
+      },
+      "response": {
+        "status": {
+          "code": 200,
+          "message": "OK"
+        },
+        "headers": {},
+        "body": {
+          "parsed_json": {
+            "args": {},
+            "data": "{\"update\": \"value\"}",
+            "files": {},
+            "form": {},
+            "headers": {
+              "Accept": "*/*",
+              "Accept-Encoding": "gzip, deflate",
+              "Content-Length": "19",
+              "Content-Type": "application/json",
+              "Host": "httpbin.org",
+              "User-Agent": "python-requests/2.32.3",
+              "X-Amzn-Trace-Id": "Root=1-680f7261-631f6aae6a8ae85365354c87"
+            },
+            "json": {
+              "update": "value"
+            },
+            "origin": "x.x.x.x",
+            "url": "https://httpbin.org/put"
+          }
+        }
+      }
+    }
+  ]
+}
diff --git a/tests/vcr_cassettes/tests.unit.test_base_vcr_yaml/TestBaseVCRYAML.test_httpbin_delete.yaml b/tests/vcr_cassettes/tests.unit.test_base_vcr_yaml/TestBaseVCRYAML.test_httpbin_delete.yaml
new file mode 100644
index 000000000..7fccbf28b
--- /dev/null
+++ b/tests/vcr_cassettes/tests.unit.test_base_vcr_yaml/TestBaseVCRYAML.test_httpbin_delete.yaml
@@ -0,0 +1,31 @@
+interactions:
+- request:
+    body: null
+    headers: {}
+    method: DELETE
+    uri: https://httpbin.org/delete
+  response:
+    body:
+      string: |-
+        {
+          "args": {},
+          "data": "",
+          "files": {},
+          "form": {},
+          "headers": {
+            "Accept": "*/*",
+            "Accept-Encoding": "gzip, deflate",
+            "Content-Length": "0",
+            "Host": "httpbin.org",
+            "User-Agent": "python-requests/2.32.3",
+            "X-Amzn-Trace-Id": "Root=1-680f7294-550da7df2956737310f29c0c"
+          },
+          "json": null,
+          "origin": "x.x.x.x",
+          "url": "https://httpbin.org/delete"
+        }
+    headers: {}
+    status:
+      code: 200
+      message: OK
+version: 1
diff --git a/tests/vcr_cassettes/tests.unit.test_base_vcr_yaml/TestBaseVCRYAML.test_httpbin_get.yaml b/tests/vcr_cassettes/tests.unit.test_base_vcr_yaml/TestBaseVCRYAML.test_httpbin_get.yaml
new file mode 100644
index 000000000..e4e5b86f1
--- /dev/null
+++ b/tests/vcr_cassettes/tests.unit.test_base_vcr_yaml/TestBaseVCRYAML.test_httpbin_get.yaml
@@ -0,0 +1,28 @@
+interactions:
+- request:
+    body: null
+    headers: {}
+    method: GET
+    uri: https://httpbin.org/get?test=value
+  response:
+    body:
+      string: |-
+        {
+          "args": {
+            "test": "value"
+          },
+          "headers": {
+            "Accept": "*/*",
+            "Accept-Encoding": "gzip, deflate",
+            "Host": "httpbin.org",
+            "User-Agent": "python-requests/2.32.3",
+            "X-Amzn-Trace-Id": "Root=1-680f728f-7e7ba4866bd0c4c847de2cc2"
+          },
+          "origin": "x.x.x.x",
+          "url": "https://httpbin.org/get?test=value"
+        }
+    headers: {}
+    status:
+      code: 200
+      message: OK
+version: 1
diff --git a/tests/vcr_cassettes/tests.unit.test_base_vcr_yaml/TestBaseVCRYAML.test_httpbin_post.yaml b/tests/vcr_cassettes/tests.unit.test_base_vcr_yaml/TestBaseVCRYAML.test_httpbin_post.yaml
new file mode 100644
index 000000000..3ab6ee8b7
--- /dev/null
+++ b/tests/vcr_cassettes/tests.unit.test_base_vcr_yaml/TestBaseVCRYAML.test_httpbin_post.yaml
@@ -0,0 +1,39 @@
+interactions:
+- request:
+    body: |-
+      {
+        "name": "atlan",
+        "type": "integration-test"
+      }
+    headers: {}
+    method: POST
+    uri: https://httpbin.org/post
+  response:
+    body:
+      string: |-
+        {
+          "args": {},
+          "data": "{\"name\": \"atlan\", \"type\": \"integration-test\"}",
+          "files": {},
+          "form": {},
+          "headers": {
+            "Accept": "*/*",
+            "Accept-Encoding": "gzip, deflate",
+            "Content-Length": "45",
+            "Content-Type": "application/json",
+            "Host": "httpbin.org",
+            "User-Agent": "python-requests/2.32.3",
+            "X-Amzn-Trace-Id": "Root=1-680f7290-276efa7f015f83d24d9fdfc4"
+          },
+          "json": {
+            "name": "atlan",
+            "type": "integration-test"
+          },
+          "origin": "x.x.x.x",
+          "url": "https://httpbin.org/post"
+        }
+    headers: {}
+    status:
+      code: 200
+      message: OK
+version: 1
diff --git a/tests/vcr_cassettes/tests.unit.test_base_vcr_yaml/TestBaseVCRYAML.test_httpbin_put.yaml b/tests/vcr_cassettes/tests.unit.test_base_vcr_yaml/TestBaseVCRYAML.test_httpbin_put.yaml
new file mode 100644
index 000000000..ec1bdd256
--- /dev/null
+++ b/tests/vcr_cassettes/tests.unit.test_base_vcr_yaml/TestBaseVCRYAML.test_httpbin_put.yaml
@@ -0,0 +1,37 @@
+interactions:
+- request:
+    body: |-
+      {
+        "update": "value"
+      }
+    headers: {}
+    method: PUT
+    uri: https://httpbin.org/put
+  response:
+    body:
+      string: |-
+        {
+          "args": {},
+          "data": "{\"update\": \"value\"}",
+          "files": {},
+          "form": {},
+          "headers": {
+            "Accept": "*/*",
+            "Accept-Encoding": "gzip, deflate",
+            "Content-Length": "19",
+            "Content-Type": "application/json",
+            "Host": "httpbin.org",
+            "User-Agent": "python-requests/2.32.3",
+            "X-Amzn-Trace-Id": "Root=1-680f7292-14a3d32d1869399c2db8f571"
+          },
+          "json": {
+            "update": "value"
+          },
+          "origin": "x.x.x.x",
+          "url": "https://httpbin.org/put"
+        }
+    headers: {}
+    status:
+      code: 200
+      message: OK
+version: 1