diff --git a/planet/cli/data.py b/planet/cli/data.py
index dc0bc8e..e4fa562 100644
--- a/planet/cli/data.py
+++ b/planet/cli/data.py
@@ -364,7 +364,41 @@ async def search_delete(ctx, search_id):
         await cl.delete_search(search_id)
 
 
-# TODO: search_update()".
+@data.command()
+@click.pass_context
+@translate_exceptions
+@coro
+@click.argument('search_id')
+@click.argument('name')
+@click.argument("item_types",
+                type=types.CommaSeparatedString(),
+                callback=check_item_types)
+@click.argument('filter', type=types.JSON())
+@click.option('--daily-email',
+              is_flag=True,
+              help='Send a daily email when new results are added.')
+@pretty
+async def search_update(ctx,
+                        search_id,
+                        name,
+                        item_types,
+                        filter,
+                        daily_email,
+                        pretty):
+    """Update a saved search with the given search request.
+
+    This function outputs a full JSON description of the updated search,
+    optionally pretty-printed.
+    """
+    async with data_client(ctx) as cl:
+        items = await cl.update_search(search_id,
+                                       name,
+                                       item_types,
+                                       filter,
+                                       daily_email)
+        echo_json(items, pretty)
+
+
 # TODO: search_run()".
 # TODO: item_get()".
 # TODO: asset_activate()".

diff --git a/tests/integration/test_data_cli.py b/tests/integration/test_data_cli.py
index 881693c..223f3b3 100644
--- a/tests/integration/test_data_cli.py
+++ b/tests/integration/test_data_cli.py
@@ -54,6 +54,7 @@ def test_data_command_registered(invoke):
     assert "search-create" in result.output
     assert "search-get" in result.output
     assert "search-delete" in result.output
+    assert "search-update" in result.output
     # Add other sub-commands here.
 
 
@@ -87,6 +88,12 @@ def default_filters():
     return [PERMISSION_FILTER, STD_QUALITY_FILTER]
 
 
+@pytest.fixture
+def search_filter(get_test_file_json):
+    filename = 'data_search_filter_2022-01.json'
+    return get_test_file_json(filename)
+
+
 @pytest.fixture
 def assert_and_filters_equal():
     """Check for equality when the order of the config list doesn't matter"""
@@ -725,8 +732,54 @@ def test_search_delete_nonexistant_search_id(invoke, search_id, search_result):
     assert result.exit_code == 1
 
 
+@pytest.mark.parametrize("item_types",
+                         ['PSScene', 'SkySatScene', 'PSScene, SkySatScene'])
+@respx.mock
+def test_search_update_success(invoke,
+                               search_id,
+                               search_result,
+                               item_types,
+                               search_filter):
+    update_url = f'{TEST_SEARCHES_URL}/{search_id}'
+    mock_resp = httpx.Response(HTTPStatus.OK, json=search_result)
+    respx.put(update_url).return_value = mock_resp
+
+    name = "search_name"
+
+    result = invoke([
+        'search-update',
+        search_id,
+        name,
+        item_types,
+        json.dumps(search_filter)
+    ])
+
+    assert not result.exception
+
+
+@respx.mock
+def test_search_update_fail(invoke, search_id, search_filter):
+    update_url = f'{TEST_SEARCHES_URL}/{search_id}'
+    error_json = {"message": "Error message"}
+    mock_resp = httpx.Response(404, json=error_json)
+    respx.put(update_url).return_value = mock_resp
+
+    name = "search_name"
+    item_types = "PSScene"
+
+    result = invoke([
+        'search-update',
+        search_id,
+        name,
+        item_types,
+        json.dumps(search_filter)
+    ])
+
+    assert result.output.startswith("Error")
+    assert result.exception
+
+
 # TODO: basic test for "planet data search-create".
-# TODO: basic test for "planet data search-update".
 # TODO: basic test for "planet data search-get".
 # TODO: basic test for "planet data search-list".
 # TODO: basic test for "planet data search-run".

Implement CLI command: planet data search-update
As specified in https://github.com/planetlabs/planet-client-python/blob/main/design-docs/CLI-Data.md#search-update 
tests/integration/test_data_cli.py::test_data_command_registered tests/integration/test_data_cli.py::test_search_update_success[PSScene] tests/integration/test_data_cli.py::test_search_update_success[SkySatScene] tests/integration/test_data_cli.py::test_search_update_success[PSScene, tests/integration/test_data_cli.py::test_search_update_fail
tests/integration/test_data_cli.py::test_data_search_command_registered tests/integration/test_data_cli.py::test_data_filter_defaults[None-None-None-None] tests/integration/test_data_cli.py::test_data_filter_defaults[None-None---permission=False-p_remove1] tests/integration/test_data_cli.py::test_data_filter_defaults[--std-quality=False-s_remove1-None-None] tests/integration/test_data_cli.py::test_data_filter_defaults[--std-quality=False-s_remove1---permission=False-p_remove1] tests/integration/test_data_cli.py::test_data_filter_asset[ortho_analytic_8b_sr-expected0] tests/integration/test_data_cli.py::test_data_filter_asset[ortho_analytic_8b_sr,ortho_analytic_4b_sr-expected1] tests/integration/test_data_cli.py::test_data_filter_asset[ortho_analytic_8b_sr tests/integration/test_data_cli.py::test_data_filter_date_range_success tests/integration/test_data_cli.py::test_data_filter_date_range_invalid tests/integration/test_data_cli.py::test_data_filter_geom[geom_geojson] tests/integration/test_data_cli.py::test_data_filter_geom[feature_geojson] tests/integration/test_data_cli.py::test_data_filter_geom[featurecollection_geojson] tests/integration/test_data_cli.py::test_data_filter_number_in_success tests/integration/test_data_cli.py::test_data_filter_number_in_badparam tests/integration/test_data_cli.py::test_data_filter_range tests/integration/test_data_cli.py::test_data_filter_string_in tests/integration/test_data_cli.py::test_data_filter_update tests/integration/test_data_cli.py::test_data_search_cmd_filter_invalid_json[PSScene-{1:1}] tests/integration/test_data_cli.py::test_data_search_cmd_filter_invalid_json[PSScene-{"foo"}] tests/integration/test_data_cli.py::test_data_search_cmd_filter_invalid_json[SkySatScene-{1:1}] tests/integration/test_data_cli.py::test_data_search_cmd_filter_invalid_json[SkySatScene-{"foo"}] tests/integration/test_data_cli.py::test_data_search_cmd_filter_invalid_json[PSScene, tests/integration/test_data_cli.py::test_data_search_cmd_filter_success[PSScene] tests/integration/test_data_cli.py::test_data_search_cmd_filter_success[SkySatScene] tests/integration/test_data_cli.py::test_data_search_cmd_filter_success[PSScene, tests/integration/test_data_cli.py::test_data_search_cmd_sort_success tests/integration/test_data_cli.py::test_data_search_cmd_sort_invalid tests/integration/test_data_cli.py::test_data_search_cmd_limit[None-100] tests/integration/test_data_cli.py::test_data_search_cmd_limit[0-102] tests/integration/test_data_cli.py::test_data_search_cmd_limit[1-1] tests/integration/test_data_cli.py::test_data_search_create_filter_invalid_json[PSScene-{1:1}] tests/integration/test_data_cli.py::test_data_search_create_filter_invalid_json[PSScene-{"foo"}] tests/integration/test_data_cli.py::test_data_search_create_filter_invalid_json[SkySatScene-{1:1}] tests/integration/test_data_cli.py::test_data_search_create_filter_invalid_json[SkySatScene-{"foo"}] tests/integration/test_data_cli.py::test_data_search_create_filter_invalid_json[PSScene, tests/integration/test_data_cli.py::test_data_search_create_filter_success[PSScene] tests/integration/test_data_cli.py::test_data_search_create_filter_success[SkySatScene] tests/integration/test_data_cli.py::test_data_search_create_filter_success[PSScene, tests/integration/test_data_cli.py::test_search_create_daily_email tests/integration/test_data_cli.py::test_data_stats_invalid_filter[{1:1}] tests/integration/test_data_cli.py::test_data_stats_invalid_filter[{"foo"}] tests/integration/test_data_cli.py::test_data_stats_invalid_interval[None-1-PSScene] tests/integration/test_data_cli.py::test_data_stats_invalid_interval[None-1-SkySatScene] tests/integration/test_data_cli.py::test_data_stats_invalid_interval[None-1-PSScene, tests/integration/test_data_cli.py::test_data_stats_invalid_interval[hou-2-PSScene] tests/integration/test_data_cli.py::test_data_stats_invalid_interval[hou-2-SkySatScene] tests/integration/test_data_cli.py::test_data_stats_invalid_interval[hou-2-PSScene, tests/integration/test_data_cli.py::test_data_stats_invalid_interval[hour-0-PSScene] tests/integration/test_data_cli.py::test_data_stats_invalid_interval[hour-0-SkySatScene] tests/integration/test_data_cli.py::test_data_stats_invalid_interval[hour-0-PSScene, tests/integration/test_data_cli.py::test_data_stats_success[hour-PSScene] tests/integration/test_data_cli.py::test_data_stats_success[hour-SkySatScene] tests/integration/test_data_cli.py::test_data_stats_success[hour-PSScene, tests/integration/test_data_cli.py::test_data_stats_success[day-PSScene] tests/integration/test_data_cli.py::test_data_stats_success[day-SkySatScene] tests/integration/test_data_cli.py::test_data_stats_success[day-PSScene, tests/integration/test_data_cli.py::test_data_stats_success[week-PSScene] tests/integration/test_data_cli.py::test_data_stats_success[week-SkySatScene] tests/integration/test_data_cli.py::test_data_stats_success[week-PSScene, tests/integration/test_data_cli.py::test_data_stats_success[month-PSScene] tests/integration/test_data_cli.py::test_data_stats_success[month-SkySatScene] tests/integration/test_data_cli.py::test_data_stats_success[month-PSScene, tests/integration/test_data_cli.py::test_data_stats_success[year-PSScene] tests/integration/test_data_cli.py::test_data_stats_success[year-SkySatScene] tests/integration/test_data_cli.py::test_data_stats_success[year-PSScene, tests/integration/test_data_cli.py::test_search_get tests/integration/test_data_cli.py::test_search_get_id_not_found tests/integration/test_data_cli.py::test_search_delete_success tests/integration/test_data_cli.py::test_search_delete_nonexistant_search_id