diff --git a/backend/src/baserow/contrib/database/api/rows/views.py b/backend/src/baserow/contrib/database/api/rows/views.py
index 7c48c21c1..dd5e237f7 100644
--- a/backend/src/baserow/contrib/database/api/rows/views.py
+++ b/backend/src/baserow/contrib/database/api/rows/views.py
@@ -54,6 +54,7 @@ from baserow.contrib.database.api.tokens.authentications import TokenAuthenticat
 from baserow.contrib.database.api.tokens.errors import ERROR_NO_PERMISSION_TO_TABLE
 from baserow.contrib.database.api.utils import (
     extract_link_row_joins_from_request,
+    extract_send_webhook_events_from_params,
     extract_user_field_names_from_params,
     get_include_exclude_fields,
 )
@@ -445,6 +446,16 @@ class RowsView(APIView):
                     "field names (e.g., field_123)."
                 ),
             ),
+            OpenApiParameter(
+                name="send_webhook_events",
+                location=OpenApiParameter.QUERY,
+                type=OpenApiTypes.BOOL,
+                description=(
+                    "A flag query parameter that triggers webhooks after the operation,"
+                    " if set to `y`, `yes`, `true`, `t`, `on`, `1`, `or` left empty. "
+                    "Defaults to `true`"
+                ),
+            ),
             CLIENT_SESSION_ID_SCHEMA_PARAMETER,
             CLIENT_UNDO_REDO_ACTION_GROUP_ID_SCHEMA_PARAMETER,
         ],
@@ -514,6 +525,7 @@ class RowsView(APIView):
         )
 
         user_field_names = extract_user_field_names_from_params(request.GET)
+        send_webhook_events = extract_send_webhook_events_from_params(request.GET)
 
         model = table.get_model()
 
@@ -537,6 +549,7 @@ class RowsView(APIView):
                 model=model,
                 before_row=before_row,
                 user_field_names=user_field_names,
+                send_webhook_events=send_webhook_events,
             )
         except ValidationError as e:
             raise RequestBodyValidationException(detail=e.message)
@@ -771,6 +784,16 @@ class RowView(APIView):
                     "field names (e.g., field_123)."
                 ),
             ),
+            OpenApiParameter(
+                name="send_webhook_events",
+                location=OpenApiParameter.QUERY,
+                type=OpenApiTypes.BOOL,
+                description=(
+                    "A flag query parameter that triggers webhooks after the operation,"
+                    " if set to `y`, `yes`, `true`, `t`, `on`, `1`, `or` left empty. "
+                    "Defaults to `true`"
+                ),
+            ),
             CLIENT_SESSION_ID_SCHEMA_PARAMETER,
             CLIENT_UNDO_REDO_ACTION_GROUP_ID_SCHEMA_PARAMETER,
         ],
@@ -833,6 +856,7 @@ class RowView(APIView):
         TokenHandler().check_table_permissions(request, "update", table, False)
 
         user_field_names = extract_user_field_names_from_params(request.GET)
+        send_webhook_events = extract_send_webhook_events_from_params(request.GET)
         field_ids, field_names = None, None
 
         if user_field_names:
@@ -852,7 +876,11 @@ class RowView(APIView):
         try:
             data["id"] = int(row_id)
             row = action_type_registry.get_by_type(UpdateRowsActionType).do(
-                request.user, table, [data], model
+                request.user,
+                table,
+                [data],
+                model=model,
+                send_webhook_events=send_webhook_events,
             )[0]
         except ValidationError as exc:
             raise RequestBodyValidationException(detail=exc.message) from exc
@@ -877,6 +905,16 @@ class RowView(APIView):
                 type=OpenApiTypes.INT,
                 description="Deletes the row related to the value.",
             ),
+            OpenApiParameter(
+                name="send_webhook_events",
+                location=OpenApiParameter.QUERY,
+                type=OpenApiTypes.BOOL,
+                description=(
+                    "A flag query parameter that triggers webhooks after the operation,"
+                    " if set to `y`, `yes`, `true`, `t`, `on`, `1`, `or` left empty. "
+                    "Defaults to `true`"
+                ),
+            ),
             CLIENT_SESSION_ID_SCHEMA_PARAMETER,
             CLIENT_UNDO_REDO_ACTION_GROUP_ID_SCHEMA_PARAMETER,
         ],
@@ -913,11 +951,13 @@ class RowView(APIView):
         table_id.
         """
 
+        send_webhook_events = extract_send_webhook_events_from_params(request.GET)
+
         table = TableHandler().get_table(table_id)
         TokenHandler().check_table_permissions(request, "delete", table, False)
 
         action_type_registry.get_by_type(DeleteRowActionType).do(
-            request.user, table, row_id
+            request.user, table, row_id, send_webhook_events=send_webhook_events
         )
 
         return Response(status=204)
@@ -961,6 +1001,16 @@ class RowMoveView(APIView):
                     "field names (e.g., field_123)."
                 ),
             ),
+            OpenApiParameter(
+                name="send_webhook_events",
+                location=OpenApiParameter.QUERY,
+                type=OpenApiTypes.BOOL,
+                description=(
+                    "A flag query parameter that triggers webhooks after the operation,"
+                    " if set to `y`, `yes`, `true`, `t`, `on`, `1`, `or` left empty. "
+                    "Defaults to `true`"
+                ),
+            ),
             CLIENT_SESSION_ID_SCHEMA_PARAMETER,
             CLIENT_UNDO_REDO_ACTION_GROUP_ID_SCHEMA_PARAMETER,
         ],
@@ -1001,6 +1051,7 @@ class RowMoveView(APIView):
         TokenHandler().check_table_permissions(request, "update", table, False)
 
         user_field_names = extract_user_field_names_from_params(request.GET)
+        send_webhook_events = extract_send_webhook_events_from_params(request.GET)
 
         model = table.get_model()
 
@@ -1014,7 +1065,12 @@ class RowMoveView(APIView):
         )
 
         row = action_type_registry.get_by_type(MoveRowActionType).do(
-            request.user, table, row_id, before_row=before_row, model=model
+            request.user,
+            table,
+            row_id,
+            before_row=before_row,
+            model=model,
+            send_webhook_events=send_webhook_events,
         )
 
         serializer_class = get_row_serializer_class(
@@ -1055,6 +1111,16 @@ class BatchRowsView(APIView):
                     "field names (e.g., field_123)."
                 ),
             ),
+            OpenApiParameter(
+                name="send_webhook_events",
+                location=OpenApiParameter.QUERY,
+                type=OpenApiTypes.BOOL,
+                description=(
+                    "A flag query parameter that triggers webhooks after the operation,"
+                    " if set to `y`, `yes`, `true`, `t`, `on`, `1`, `or` left empty. "
+                    "Defaults to `true`"
+                ),
+            ),
             CLIENT_SESSION_ID_SCHEMA_PARAMETER,
             CLIENT_UNDO_REDO_ACTION_GROUP_ID_SCHEMA_PARAMETER,
         ],
@@ -1120,6 +1186,7 @@ class BatchRowsView(APIView):
         model = table.get_model()
 
         user_field_names = extract_user_field_names_from_params(request.GET)
+        send_webhook_events = extract_send_webhook_events_from_params(request.GET)
         before_id = query_params.get("before")
         before_row = (
             RowHandler().get_row(request.user, table, before_id, model)
@@ -1139,7 +1206,12 @@ class BatchRowsView(APIView):
 
         try:
             rows = action_type_registry.get_by_type(CreateRowsActionType).do(
-                request.user, table, data["items"], before_row, model
+                request.user,
+                table,
+                data["items"],
+                before_row,
+                model=model,
+                send_webhook_events=send_webhook_events,
             )
         except ValidationError as exc:
             raise RequestBodyValidationException(detail=exc.message)
@@ -1173,6 +1245,16 @@ class BatchRowsView(APIView):
                     "field names (e.g., field_123)."
                 ),
             ),
+            OpenApiParameter(
+                name="send_webhook_events",
+                location=OpenApiParameter.QUERY,
+                type=OpenApiTypes.BOOL,
+                description=(
+                    "A flag query parameter that triggers webhooks after the operation,"
+                    " if set to `y`, `yes`, `true`, `t`, `on`, `1`, `or` left empty. "
+                    "Defaults to `true`"
+                ),
+            ),
             CLIENT_SESSION_ID_SCHEMA_PARAMETER,
             CLIENT_UNDO_REDO_ACTION_GROUP_ID_SCHEMA_PARAMETER,
         ],
@@ -1237,6 +1319,7 @@ class BatchRowsView(APIView):
         model = table.get_model()
 
         user_field_names = extract_user_field_names_from_params(request.GET)
+        send_webhook_events = extract_send_webhook_events_from_params(request.GET)
 
         row_validation_serializer = get_row_serializer_class(
             model,
@@ -1253,7 +1336,11 @@ class BatchRowsView(APIView):
 
         try:
             rows = action_type_registry.get_by_type(UpdateRowsActionType).do(
-                request.user, table, data["items"], model
+                request.user,
+                table,
+                data["items"],
+                model=model,
+                send_webhook_events=send_webhook_events,
             )
         except ValidationError as e:
             raise RequestBodyValidationException(detail=e.message)
@@ -1280,6 +1367,16 @@ class BatchDeleteRowsView(APIView):
                 type=OpenApiTypes.INT,
                 description="Deletes the rows in the table related to the value.",
             ),
+            OpenApiParameter(
+                name="send_webhook_events",
+                location=OpenApiParameter.QUERY,
+                type=OpenApiTypes.BOOL,
+                description=(
+                    "A flag query parameter that triggers webhooks after the operation,"
+                    " if set to `y`, `yes`, `true`, `t`, `on`, `1`, `or` left empty. "
+                    "Defaults to `true`"
+                ),
+            ),
             CLIENT_SESSION_ID_SCHEMA_PARAMETER,
             CLIENT_UNDO_REDO_ACTION_GROUP_ID_SCHEMA_PARAMETER,
         ],
@@ -1327,10 +1424,13 @@ class BatchDeleteRowsView(APIView):
         table = TableHandler().get_table(table_id)
         TokenHandler().check_table_permissions(request, "delete", table, False)
 
+        send_webhook_events = extract_send_webhook_events_from_params(request.GET)
+
         action_type_registry.get_by_type(DeleteRowsActionType).do(
             request.user,
             table,
             row_ids=data["items"],
+            send_webhook_events=send_webhook_events,
         )
 
         return Response(status=204)
diff --git a/backend/src/baserow/contrib/database/api/utils.py b/backend/src/baserow/contrib/database/api/utils.py
index bd90b898f..e0005ad0a 100644
--- a/backend/src/baserow/contrib/database/api/utils.py
+++ b/backend/src/baserow/contrib/database/api/utils.py
@@ -174,6 +174,20 @@ def extract_user_field_names_from_params(query_params):
     return str_to_bool(value)
 
 
+def extract_send_webhook_events_from_params(query_params) -> bool:
+    """
+    Extracts the send_webhook_events parameter from the query_params and returns
+    boolean value. Defaults to true if not provided or empty.
+    """
+
+    value = query_params.get("send_webhook_events")
+
+    if value is None or value == "":
+        return True
+
+    return str_to_bool(value)
+
+
 @dataclass
 class LinkedTargetField:
     field_id: int
diff --git a/backend/src/baserow/contrib/database/rows/actions.py b/backend/src/baserow/contrib/database/rows/actions.py
index bfac48e42..e52088efa 100755
--- a/backend/src/baserow/contrib/database/rows/actions.py
+++ b/backend/src/baserow/contrib/database/rows/actions.py
@@ -58,6 +58,7 @@ class CreateRowActionType(UndoableActionType):
         model: Optional[Type[GeneratedTableModel]] = None,
         before_row: Optional[GeneratedTableModel] = None,
         user_field_names: bool = False,
+        send_webhook_events: bool = True,
     ) -> GeneratedTableModel:
         """
         Creates a new row for a given table with the provided values if the user
@@ -76,6 +77,8 @@ class CreateRowActionType(UndoableActionType):
             instance.
         :param user_field_names: Whether or not the values are keyed by the internal
             Baserow field name (field_1,field_2 etc) or by the user field names.
+        :param send_webhook_events: If set the false then the webhooks will not be
+            triggered. Defaults to true.
         :return: The created row instance.
         """
 
@@ -91,6 +94,7 @@ class CreateRowActionType(UndoableActionType):
             model=model,
             before_row=before_row,
             user_field_names=user_field_names,
+            send_webhook_events=send_webhook_events,
         )
 
         workspace = table.database.workspace
@@ -148,6 +152,7 @@ class CreateRowsActionType(UndoableActionType):
         rows_values: List[Dict[str, Any]],
         before_row: Optional[GeneratedTableModel] = None,
         model: Optional[Type[GeneratedTableModel]] = None,
+        send_webhook_events: bool = True,
     ) -> List[GeneratedTableModel]:
         """
         Creates rows for a given table with the provided values if the user
@@ -163,6 +168,8 @@ class CreateRowsActionType(UndoableActionType):
             the row with this id.
         :param model: If the correct model has already been generated it can be
             provided so that it does not have to be generated for a second time.
+        :param send_webhook_events: If set the false then the webhooks will not be
+            triggered. Defaults to true.
         :return: The created list of rows instances.
         """
 
@@ -177,6 +184,7 @@ class CreateRowsActionType(UndoableActionType):
             rows_values,
             before_row=before_row,
             model=model,
+            send_webhook_events=send_webhook_events,
         )
 
         workspace = table.database.workspace
@@ -327,6 +335,7 @@ class DeleteRowActionType(UndoableActionType):
         table: Table,
         row_id: int,
         model: Optional[Type[GeneratedTableModel]] = None,
+        send_webhook_events: bool = True,
     ):
         """
         Deletes an existing row of the given table and with row_id.
@@ -339,6 +348,8 @@ class DeleteRowActionType(UndoableActionType):
         :param row_id: The id of the row that must be deleted.
         :param model: If the correct model has already been generated, it can be
             provided so that it does not have to be generated for a second time.
+        :param send_webhook_events: If set the false then the webhooks will not be
+            triggered. Defaults to true.
         :raises RowDoesNotExist: When the row with the provided id does not exist.
         """
 
@@ -347,7 +358,9 @@ class DeleteRowActionType(UndoableActionType):
                 "Can't delete rows because it has a data sync."
             )
 
-        RowHandler().delete_row_by_id(user, table, row_id, model=model)
+        RowHandler().delete_row_by_id(
+            user, table, row_id, model=model, send_webhook_events=send_webhook_events
+        )
 
         database = table.database
         params = cls.Params(table.id, table.name, database.id, database.name, row_id)
@@ -399,6 +412,7 @@ class DeleteRowsActionType(UndoableActionType):
         table: Table,
         row_ids: List[int],
         model: Optional[Type[GeneratedTableModel]] = None,
+        send_webhook_events: bool = True,
     ):
         """
         Deletes rows of the given table with the given row_ids.
@@ -411,6 +425,8 @@ class DeleteRowsActionType(UndoableActionType):
         :param row_ids: The id of the row that must be deleted.
         :param model: If the correct model has already been generated, it can be
             provided so that it does not have to be generated for a second time.
+        :param send_webhook_events: If set the false then the webhooks will not be
+            triggered. Defaults to true.
         :raises RowDoesNotExist: When the row with the provided id does not exist.
         """
 
@@ -419,7 +435,9 @@ class DeleteRowsActionType(UndoableActionType):
                 "Can't delete rows because it has a data sync."
             )
 
-        trashed_rows_entry = RowHandler().delete_rows(user, table, row_ids, model=model)
+        trashed_rows_entry = RowHandler().delete_rows(
+            user, table, row_ids, model=model, send_webhook_events=send_webhook_events
+        )
 
         workspace = table.database.workspace
         params = cls.Params(
@@ -548,6 +566,7 @@ class MoveRowActionType(UndoableActionType):
         row_id: int,
         before_row: Optional[GeneratedTableModel] = None,
         model: Optional[Type[GeneratedTableModel]] = None,
+        send_webhook_events: bool = True,
     ) -> GeneratedTableModelForUpdate:
         """
         Moves the row before another row or to the end if no before row is provided.
@@ -566,6 +585,8 @@ class MoveRowActionType(UndoableActionType):
             instance. Otherwise the row will be moved to the end.
         :param model: If the correct model has already been generated, it can be
             provided so that it does not have to be generated for a second time.
+        :param send_webhook_events: If set the false then the webhooks will not be
+            triggered. Defaults to true.
         """
 
         if model is None:
@@ -577,7 +598,12 @@ class MoveRowActionType(UndoableActionType):
         original_row_order = row.order
 
         updated_row = row_handler.move_row(
-            user, table, row, before_row=before_row, model=model
+            user,
+            table,
+            row,
+            before_row=before_row,
+            model=model,
+            send_webhook_events=send_webhook_events,
         )
 
         rows_displacement = get_rows_displacement(
@@ -762,6 +788,7 @@ class UpdateRowsActionType(UndoableActionType):
         table: Table,
         rows_values: List[Dict[str, Any]],
         model: Optional[Type[GeneratedTableModel]] = None,
+        send_webhook_events: bool = True,
     ) -> List[GeneratedTableModelForUpdate]:
         """
         Updates field values in batch based on provided rows with the new values.
@@ -776,6 +803,8 @@ class UpdateRowsActionType(UndoableActionType):
             field ids plus the id of the row.
         :param model: If the correct model has already been generated it can be
             provided so that it does not have to be generated for a second time.
+        :param send_webhook_events: If set the false then the webhooks will not be
+            triggered. Defaults to true.
         :return: The updated rows.
         """
 
@@ -786,6 +815,7 @@ class UpdateRowsActionType(UndoableActionType):
             table,
             rows_values,
             model=model,
+            send_webhook_events=send_webhook_events,
         )
         updated_rows = result.updated_rows
 
diff --git a/backend/src/baserow/contrib/database/rows/handler.py b/backend/src/baserow/contrib/database/rows/handler.py
index 4363167ec..2c5de2b93 100644
--- a/backend/src/baserow/contrib/database/rows/handler.py
+++ b/backend/src/baserow/contrib/database/rows/handler.py
@@ -667,6 +667,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)):
         before_row: Optional[GeneratedTableModel] = None,
         user_field_names: bool = False,
         values_already_prepared: bool = False,
+        send_webhook_events: bool = True,
     ) -> GeneratedTableModel:
         """
         Creates a new row for a given table with the provided values if the user
@@ -685,6 +686,8 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)):
         :param values_already_prepared: Whether or not the values are already sanitized
             and validated for every field and can be used directly by the handler
             without any further check.
+        :param send_webhook_events: If set the false then the webhooks will not be
+            triggered. Defaults to true.
         :return: The created row instance.
         """
 
@@ -706,6 +709,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)):
             before_row,
             user_field_names,
             values_already_prepared=values_already_prepared,
+            send_webhook_events=send_webhook_events,
         )
 
     def force_create_row(
@@ -717,6 +721,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)):
         before: Optional[GeneratedTableModel] = None,
         user_field_names: bool = False,
         values_already_prepared: bool = False,
+        send_webhook_events: bool = True,
     ):
         """
         Creates a new row for a given table with the provided values.
@@ -735,6 +740,8 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)):
         :param values_already_prepared: Whether or not the values are already sanitized
             and validated for every field and can be used directly by the handler
             without any further check.
+        :param send_webhook_events: If set the false then the webhooks will not be
+            triggered. Defaults to true.
         :return: The created row instance.
         :rtype: Model
         """
@@ -806,7 +813,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)):
             table=table,
             model=model,
             send_realtime_update=True,
-            send_webhook_events=True,
+            send_webhook_events=send_webhook_events,
             rows_values_refreshed_from_db=False,
             m2m_change_tracker=m2m_change_tracker,
         )
@@ -2028,6 +2035,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)):
         row: GeneratedTableModelForUpdate,
         before_row: Optional[GeneratedTableModel] = None,
         model: Optional[Type[GeneratedTableModel]] = None,
+        send_webhook_events: bool = True,
     ) -> GeneratedTableModelForUpdate:
         """
         Updates the row order value.
@@ -2039,6 +2047,8 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)):
             instance. Otherwise the row will be moved to the end.
         :param model: If the correct model has already been generated, it can be
             provided so that it does not have to be generated for a second time.
+        :param send_webhook_events: If set the false then the webhooks will not be
+            triggered. Defaults to true.
         """
 
         workspace = table.database.workspace
@@ -2090,6 +2100,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)):
             before_return=before_return,
             updated_field_ids=[],
             prepared_rows_values=None,
+            send_webhook_events=send_webhook_events,
         )
 
         return row
diff --git a/backend/tests/baserow/contrib/database/api/rows/test_batch_rows_views.py b/backend/tests/baserow/contrib/database/api/rows/test_batch_rows_views.py
index 0fd4e6008..f01a8f3da 100644
--- a/backend/tests/baserow/contrib/database/api/rows/test_batch_rows_views.py
+++ b/backend/tests/baserow/contrib/database/api/rows/test_batch_rows_views.py
@@ -1,4 +1,5 @@
 from decimal import Decimal
+from unittest.mock import patch
 
 from django.conf import settings
 from django.db import connection
@@ -289,6 +290,57 @@ def test_batch_create_rows(api_client, data_fixture):
     assert row_2.needs_background_update
 
 
+@pytest.mark.django_db(transaction=True)
+@pytest.mark.api_rows
+def test_batch_create_rows_with_disabled_webhook_events(api_client, data_fixture):
+    user, jwt_token = data_fixture.create_user_and_token()
+    table = data_fixture.create_database_table(user=user)
+    text_field = data_fixture.create_text_field(
+        table=table, order=0, name="Color", text_default="white"
+    )
+    number_field = data_fixture.create_number_field(
+        table=table, order=1, name="Horsepower"
+    )
+    boolean_field = data_fixture.create_boolean_field(
+        table=table, order=2, name="For sale"
+    )
+
+    data_fixture.create_table_webhook(
+        table=table,
+        user=user,
+        request_method="POST",
+        url="http://localhost",
+        events=[],
+    )
+
+    url = reverse("api:database:rows:batch", kwargs={"table_id": table.id})
+    request_body = {
+        "items": [
+            {
+                f"field_{text_field.id}": "green",
+                f"field_{number_field.id}": 120,
+                f"field_{boolean_field.id}": True,
+            },
+            {
+                f"field_{text_field.id}": "yellow",
+                f"field_{number_field.id}": 240,
+                f"field_{boolean_field.id}": False,
+            },
+        ]
+    }
+
+    with patch("baserow.contrib.database.webhooks.registries.call_webhook.delay") as m:
+        response = api_client.post(
+            f"{url}?send_webhook_events=false",
+            request_body,
+            format="json",
+            HTTP_AUTHORIZATION=f"JWT {jwt_token}",
+        )
+
+        assert response.status_code == HTTP_200_OK
+        m.assert_not_called()
+
+
 @pytest.mark.django_db
 @pytest.mark.api_rows
 def test_batch_create_rows_id_field_ignored(api_client, data_fixture):
@@ -1184,6 +1236,62 @@ def test_batch_update_rows(api_client, data_fixture):
     assert row_2.needs_background_update
 
 
+@pytest.mark.django_db(transaction=True)
+@pytest.mark.api_rows
+def test_batch_update_rows_with_disabled_webhook_events(api_client, data_fixture):
+    user, jwt_token = data_fixture.create_user_and_token()
+    table = data_fixture.create_database_table(user=user)
+    text_field = data_fixture.create_text_field(
+        table=table, order=0, name="Color", text_default="white"
+    )
+    number_field = data_fixture.create_number_field(
+        table=table, order=1, name="Horsepower"
+    )
+    boolean_field = data_fixture.create_boolean_field(
+        table=table, order=2, name="For sale"
+    )
+    model = table.get_model()
+    row_1 = model.objects.create()
+    row_2 = model.objects.create()
+    model.objects.update(needs_background_update=False)
+
+    data_fixture.create_table_webhook(
+        table=table,
+        user=user,
+        request_method="POST",
+        url="http://localhost",
+        events=[],
+    )
+
+    url = reverse("api:database:rows:batch", kwargs={"table_id": table.id})
+    request_body = {
+        "items": [
+            {
+                f"id": row_1.id,
+                f"field_{text_field.id}": "green",
+                f"field_{number_field.id}": 120,
+                f"field_{boolean_field.id}": True,
+            },
+            {
+                f"id": row_2.id,
+                f"field_{text_field.id}": "yellow",
+                f"field_{number_field.id}": 240,
+                f"field_{boolean_field.id}": False,
+            },
+        ]
+    }
+
+    with patch("baserow.contrib.database.webhooks.registries.call_webhook.delay") as m:
+        response = api_client.patch(
+            f"{url}?send_webhook_events=false",
+            request_body,
+            format="json",
+            HTTP_AUTHORIZATION=f"JWT {jwt_token}",
+        )
+        assert response.status_code == HTTP_200_OK
+        m.assert_not_called()
+
+
 @pytest.mark.django_db
 @pytest.mark.api_rows
 def test_batch_update_rows_last_modified_field(api_client, data_fixture):
@@ -2275,3 +2383,34 @@ def test_batch_delete_rows_num_of_queries(api_client, data_fixture):
     assert len(delete_one_row_ctx.captured_queries) == len(
         delete_multiple_rows_ctx.captured_queries
     )
+
+
+@pytest.mark.django_db(transaction=True)
+@pytest.mark.api_rows
+def test_batch_delete_rows_disabled_webhook_events(api_client, data_fixture):
+    user, jwt_token = data_fixture.create_user_and_token()
+    table = data_fixture.create_database_table(user=user)
+    model = table.get_model()
+    row_1 = model.objects.create()
+    row_2 = model.objects.create()
+    model.objects.create()
+    url = reverse("api:database:rows:batch-delete", kwargs={"table_id": table.id})
+    request_body = {"items": [row_1.id, row_2.id]}
+
+    data_fixture.create_table_webhook(
+        table=table,
+        user=user,
+        request_method="POST",
+        url="http://localhost",
+        events=[],
+    )
+
+    with patch("baserow.contrib.database.webhooks.registries.call_webhook.delay") as m:
+        response = api_client.post(
+            f"{url}?send_webhook_events=false",
+            request_body,
+            format="json",
+            HTTP_AUTHORIZATION=f"JWT {jwt_token}",
+        )
+        assert response.status_code == HTTP_204_NO_CONTENT
+        m.assert_not_called()
diff --git a/backend/tests/baserow/contrib/database/api/rows/test_row_views.py b/backend/tests/baserow/contrib/database/api/rows/test_row_views.py
index 22675c10d..c8b4a8789 100644
--- a/backend/tests/baserow/contrib/database/api/rows/test_row_views.py
+++ b/backend/tests/baserow/contrib/database/api/rows/test_row_views.py
@@ -1,6 +1,7 @@
 import json
 from datetime import datetime, timedelta, timezone
 from decimal import Decimal
+from unittest.mock import patch
 from urllib.parse import quote
 
 from django.db import connection
@@ -1840,6 +1841,35 @@ def test_create_row(api_client, data_fixture):
     }
 
 
+@pytest.mark.django_db(transaction=True)
+def test_create_row_with_disabled_webhook_events(api_client, data_fixture):
+    user, token = data_fixture.create_user_and_token()
+    table = data_fixture.create_database_table(user=user)
+    text_field = data_fixture.create_text_field(
+        table=table, order=0, name="Color", text_default="white"
+    )
+
+    data_fixture.create_table_webhook(
+        table=table,
+        user=user,
+        request_method="POST",
+        url="http://localhost",
+        events=[],
+    )
+
+    url = reverse("api:database:rows:list", kwargs={"table_id": table.id})
+
+    with patch("baserow.contrib.database.webhooks.registries.call_webhook.delay") as m:
+        response = api_client.post(
+            f"{url}?send_webhook_events=false",
+            {f"field_{text_field.id}": "Test 1"},
+            format="json",
+            HTTP_AUTHORIZATION=f"JWT {token}",
+        )
+        assert response.status_code == HTTP_200_OK
+        m.assert_not_called()
+
+
 @pytest.mark.django_db
 def test_create_row_with_read_only_field(api_client, data_fixture):
     user, jwt_token = data_fixture.create_user_and_token()
@@ -2290,6 +2320,40 @@ def test_update_row(api_client, data_fixture):
     assert getattr(row_2, f"field_{boolean_field.id}") is False
 
 
+@pytest.mark.django_db(transaction=True)
+def test_update_row_with_disabled_webhook_events(api_client, data_fixture):
+    user, token = data_fixture.create_user_and_token()
+    table = data_fixture.create_database_table(user=user)
+    text_field = data_fixture.create_text_field(
+        table=table, order=0, name="Color", text_default="white"
+    )
+
+    model = table.get_model()
+    row_1 = model.objects.create()
+
+    data_fixture.create_table_webhook(
+        table=table,
+        user=user,
+        request_method="POST",
+        url="http://localhost",
+        events=[],
+    )
+
+    url = reverse(
+        "api:database:rows:item", kwargs={"table_id": table.id, "row_id": row_1.id}
+    )
+
+    with patch("baserow.contrib.database.webhooks.registries.call_webhook.delay") as m:
+        response = api_client.patch(
+            f"{url}?send_webhook_events=false",
+            {f"field_{text_field.id}": "Test 1"},
+            format="json",
+            HTTP_AUTHORIZATION=f"JWT {token}",
+        )
+        assert response.status_code == HTTP_200_OK
+        m.assert_not_called()
+
+
 @pytest.mark.django_db
 def test_update_row_with_read_only_field(api_client, data_fixture):
     user, jwt_token = data_fixture.create_user_and_token()
@@ -2472,6 +2536,40 @@ def test_move_row(api_client, data_fixture):
     )
 
 
+@pytest.mark.django_db(transaction=True)
+def test_move_row_with_disabled_webhook_events(api_client, data_fixture):
+    user, token = data_fixture.create_user_and_token()
+    table = data_fixture.create_database_table(user=user)
+    data_fixture.create_text_field(
+        table=table, order=0, name="Color", text_default="white"
+    )
+
+    model = table.get_model()
+    row_1 = model.objects.create()
+    row_2 = model.objects.create()
+
+    data_fixture.create_table_webhook(
+        table=table,
+        user=user,
+        request_method="POST",
+        url="http://localhost",
+        events=[],
+    )
+
+    url = reverse(
+        "api:database:rows:move", kwargs={"table_id": table.id, "row_id": row_2.id}
+    )
+
+    with patch("baserow.contrib.database.webhooks.registries.call_webhook.delay") as m:
+        response = api_client.patch(
+            f"{url}?before_id={row_1.id}&send_webhook_events=false",
+            format="json",
+            HTTP_AUTHORIZATION=f"JWT {token}",
+        )
+        assert response.status_code == HTTP_200_OK
+        m.assert_not_called()
+
+
 @pytest.mark.django_db
 def test_cannot_delete_row_by_id_with_data_sync(api_client, data_fixture):
     user, jwt_token = data_fixture.create_user_and_token()
@@ -2566,6 +2664,39 @@ def test_delete_row_by_id(api_client, data_fixture):
     assert model.objects.count() == 0
 
 
+@pytest.mark.django_db(transaction=True)
+def test_delete_row_by_id_with_disabled_webhook_events(api_client, data_fixture):
+    user, token = data_fixture.create_user_and_token()
+    table = data_fixture.create_database_table(user=user)
+    data_fixture.create_text_field(
+        table=table, order=0, name="Color", text_default="white"
+    )
+
+    model = table.get_model()
+    row_1 = model.objects.create()
+
+    data_fixture.create_table_webhook(
+        table=table,
+        user=user,
+        request_method="POST",
+        url="http://localhost",
+        events=[],
+    )
+
+    url = reverse(
+        "api:database:rows:item", kwargs={"table_id": table.id, "row_id": row_1.id}
+    )
+
+    with patch("baserow.contrib.database.webhooks.registries.call_webhook.delay") as m:
+        response = api_client.delete(
+            f"{url}?send_webhook_events=false",
+            format="json",
+            HTTP_AUTHORIZATION=f"JWT {token}",
+        )
+        assert response.status_code == HTTP_204_NO_CONTENT
+        m.assert_not_called()
+
+
 @pytest.mark.django_db
 def test_list_rows_with_attribute_names(api_client, data_fixture):
     user, jwt_token = data_fixture.create_user_and_token(
diff --git a/backend/tests/baserow/contrib/database/api/views/form/test_form_view_views.py b/backend/tests/baserow/contrib/database/api/views/form/test_form_view_views.py
index bf38bdff0..43bd78d6e 100644
--- a/backend/tests/baserow/contrib/database/api/views/form/test_form_view_views.py
+++ b/backend/tests/baserow/contrib/database/api/views/form/test_form_view_views.py
@@ -229,6 +229,7 @@ def test_create_form_view_with_webhooks(api_client, data_fixture):
             HTTP_AUTHORIZATION=f"JWT {token}",
         )
         assert m.called
+        print("CALL ARGS", m.call_args)
 
     response_json = response.json()
     assert response.status_code == HTTP_200_OK
diff --git a/changelog/entries/unreleased/feature/3085_prevent_triggering_webhook_if_query_param_is_provided_on_row.json b/changelog/entries/unreleased/feature/3085_prevent_triggering_webhook_if_query_param_is_provided_on_row.json
new file mode 100644
index 000000000..d7b27a4d4
--- /dev/null
+++ b/changelog/entries/unreleased/feature/3085_prevent_triggering_webhook_if_query_param_is_provided_on_row.json
@@ -0,0 +1,7 @@
+{
+    "type": "feature",
+    "message": "Prevent triggering webhook if query param is provided on row create update or delete endpoints",
+    "issue_number": 3085,
+    "bullet_points": [],
+    "created_at": "2024-11-19"
+}
diff --git a/web-frontend/locales/en.json b/web-frontend/locales/en.json
index 7733dc82f..6f1cb11d2 100644
--- a/web-frontend/locales/en.json
+++ b/web-frontend/locales/en.json
@@ -432,6 +432,7 @@
     "pathParameters": "Path parameters",
     "requestBodySchema": "Request body schema",
     "userFieldNamesDescription": "When the `user_field_names` GET parameter is provided and its value is one of the following: `y`, `yes`, `true`, `t`, `on`, `1`, or empty string, the field names returned by this endpoint will be the actual names of the fields.\n\nIf the `user_field_names` GET parameter is not provided, or if it does not match any of the above values, then all returned field names will be `field_` followed by the id of the field. For example `field_1` refers to the field with an id of `1`.",
+    "sendWebhookEventsDescription": "A flag query parameter that triggers webhooks after the operation, if set to `y`, `yes`, `true`, `t`, `on`, `1`, `or` left empty. Defaults to `true`",
     "singleRow": "Single",
     "batchRows": "Batch",
     "fileUploads": "File uploads"
diff --git a/web-frontend/modules/database/components/docs/sections/APIDocsTableCreateRow.vue b/web-frontend/modules/database/components/docs/sections/APIDocsTableCreateRow.vue
index 7e503ef93..cc61fe38c 100644
--- a/web-frontend/modules/database/components/docs/sections/APIDocsTableCreateRow.vue
+++ b/web-frontend/modules/database/components/docs/sections/APIDocsTableCreateRow.vue
@@ -39,6 +39,16 @@
           <APIDocsParameter :optional="true" name="before" type="integer">
             {{ $t('apiDocsTableCreateRow.before') }}
           </APIDocsParameter>
+          <APIDocsParameter
+            name="send_webhook_events"
+            :optional="true"
+            type="any"
+          >
+            <MarkdownIt
+              class="api-docs__content"
+              :content="$t('apiDocs.sendWebhookEventsDescription')"
+            />
+          </APIDocsParameter>
         </ul>
         <h4 class="api-docs__heading-4">
           {{ $t('apiDocs.requestBodySchema') }}
@@ -72,6 +82,16 @@
           <APIDocsParameter :optional="true" name="before" type="integer">
             {{ $t('apiDocsTableCreateRows.before') }}
           </APIDocsParameter>
+          <APIDocsParameter
+            name="send_webhook_events"
+            :optional="true"
+            type="any"
+          >
+            <MarkdownIt
+              class="api-docs__content"
+              :content="$t('apiDocs.sendWebhookEventsDescription')"
+            />
+          </APIDocsParameter>
         </ul>
         <h4 class="api-docs__heading-4">
           {{ $t('apiDocs.requestBodySchema') }}
diff --git a/web-frontend/modules/database/components/docs/sections/APIDocsTableDeleteRow.vue b/web-frontend/modules/database/components/docs/sections/APIDocsTableDeleteRow.vue
index 3865eee65..17a004850 100644
--- a/web-frontend/modules/database/components/docs/sections/APIDocsTableDeleteRow.vue
+++ b/web-frontend/modules/database/components/docs/sections/APIDocsTableDeleteRow.vue
@@ -33,7 +33,20 @@
           </APIDocsParameter>
         </ul>
       </div>
-      <div v-else>
+      <h4 class="api-docs__heading-4">{{ $t('apiDocs.queryParameters') }}</h4>
+      <ul class="api-docs__parameters">
+        <APIDocsParameter
+          name="send_webhook_events"
+          :optional="true"
+          type="any"
+        >
+          <MarkdownIt
+            class="api-docs__content"
+            :content="$t('apiDocs.sendWebhookEventsDescription')"
+          />
+        </APIDocsParameter>
+      </ul>
+      <div v-if="batchMode === true">
         <h4 class="api-docs__heading-4">
           {{ $t('apiDocs.requestBodySchema') }}
         </h4>
diff --git a/web-frontend/modules/database/components/docs/sections/APIDocsTableMoveRow.vue b/web-frontend/modules/database/components/docs/sections/APIDocsTableMoveRow.vue
index cae086d5a..958ee15d6 100644
--- a/web-frontend/modules/database/components/docs/sections/APIDocsTableMoveRow.vue
+++ b/web-frontend/modules/database/components/docs/sections/APIDocsTableMoveRow.vue
@@ -28,6 +28,16 @@
         <APIDocsParameter name="before_id" type="integer" :optional="true">
           {{ $t('apiDocsTableMoveRow.before') }}
         </APIDocsParameter>
+        <APIDocsParameter
+          name="send_webhook_events"
+          :optional="true"
+          type="any"
+        >
+          <MarkdownIt
+            class="api-docs__content"
+            :content="$t('apiDocs.sendWebhookEventsDescription')"
+          />
+        </APIDocsParameter>
       </ul>
     </div>
     <div class="api-docs__right">
diff --git a/web-frontend/modules/database/components/docs/sections/APIDocsTableUpdateRow.vue b/web-frontend/modules/database/components/docs/sections/APIDocsTableUpdateRow.vue
index 015ff136c..cd4d81d76 100644
--- a/web-frontend/modules/database/components/docs/sections/APIDocsTableUpdateRow.vue
+++ b/web-frontend/modules/database/components/docs/sections/APIDocsTableUpdateRow.vue
@@ -40,6 +40,16 @@
               :content="$t('apiDocs.userFieldNamesDescription')"
             />
           </APIDocsParameter>
+          <APIDocsParameter
+            name="send_webhook_events"
+            :optional="true"
+            type="any"
+          >
+            <MarkdownIt
+              class="api-docs__content"
+              :content="$t('apiDocs.sendWebhookEventsDescription')"
+            />
+          </APIDocsParameter>
         </ul>
         <h4 class="api-docs__heading-4">
           {{ $t('apiDocs.requestBodySchema') }}
@@ -68,6 +78,16 @@
               :content="$t('apiDocs.userFieldNamesDescription')"
             />
           </APIDocsParameter>
+          <APIDocsParameter
+            name="send_webhook_events"
+            :optional="true"
+            type="any"
+          >
+            <MarkdownIt
+              class="api-docs__content"
+              :content="$t('apiDocs.sendWebhookEventsDescription')"
+            />
+          </APIDocsParameter>
         </ul>
         <h4 class="api-docs__heading-4">
           {{ $t('apiDocs.requestBodySchema') }}