diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index a07b4bc..e76fadc 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -7,7 +7,9 @@ This document describes changes between each past release.
 10.5.0 (unreleased)
 ===================
 
-- Nothing changed yet.
+**New features**
+
+- Add history support (fixes #112), Thanks @FlorianKuckelkorn!
 
 
 10.4.1 (2019-05-22)
diff --git a/README.rst b/README.rst
index 2d36be3..f24b0d7 100644
--- a/README.rst
+++ b/README.rst
@@ -317,6 +317,28 @@ of them, you can specify the number of pages:
     records = client.get_records(_limit=10, pages=float('inf'))  # Infinity
 
 
+History
+-------
+
+If the built-in `history plugin <https://kinto.readthedocs.io/en/latest/api/1.x/history.html>`_ is enabled, it is possible to retrieve the history of changes:
+
+.. code-block:: python
+
+    # Get the complete history of a bucket
+    changes = client.get_history(bucket='default')
+
+    # and optionally use filters
+    hist = client.get_history(bucket='default', _limit=2, _sort='-last_modified', _since='1533762576015')
+    hist = client.get_history(bucket='default', resource_name='collection')
+
+
+The history of a bucket can also be purged with:
+
+.. code-block:: python
+
+    client.purge_history(bucket='default')
+
+
 Endpoint URLs
 -------------
 
diff --git a/kinto_http/__init__.py b/kinto_http/__init__.py
index 6955881..87dc701 100644
--- a/kinto_http/__init__.py
+++ b/kinto_http/__init__.py
@@ -47,6 +47,7 @@ class Endpoints(object):
         "batch": "{root}/batch",
         "buckets": "{root}/buckets",
         "bucket": "{root}/buckets/{bucket}",
+        "history": "{root}/buckets/{bucket}/history",
         "groups": "{root}/buckets/{bucket}/groups",
         "group": "{root}/buckets/{bucket}/groups/{group}",
         "collections": "{root}/buckets/{bucket}/collections",
@@ -862,6 +863,18 @@ class Client(object):
         resp, _ = self.session.request("delete", endpoint, headers=headers)
         return resp["data"]
 
+    def get_history(self, *, bucket=None, **kwargs):
+        endpoint = self.get_endpoint("history", bucket=bucket)
+        logger.info("Get history from bucket %r" % bucket or self._bucket_name)
+        return self._paginated(endpoint, **kwargs)
+
+    def purge_history(self, *, bucket=None, safe=True, if_match=None):
+        endpoint = self.get_endpoint('history', bucket=bucket)
+        headers = self._get_cache_headers(safe, if_match=if_match)
+        logger.info("Purge History of bucket %r" % bucket or self._bucket_name)
+        resp, _ = self.session.request('delete', endpoint, headers=headers)
+        return resp['data']
+
     def __repr__(self):
         if self._collection_name:
             endpoint = self.get_endpoint(

Add support of history plugin
See https://github.com/Kinto/kinto-http.js/#listing-bucket-history

* By bucket
* Filtrable
* Sortable
diff --git a/kinto_http/tests/functional.py b/kinto_http/tests/functional.py
index 5a7f70e..bd0f241 100644
--- a/kinto_http/tests/functional.py
+++ b/kinto_http/tests/functional.py
@@ -142,7 +142,7 @@ class FunctionalTest(unittest.TestCase):
     def test_group_creation_if_bucket_does_not_exist(self):
         with pytest.raises(KintoException) as e:
             self.client.create_group(id="payments", bucket="mozilla", data={"members": ["blah"]})
-        assert str(e).endswith(
+        assert str(e.value).endswith(
             "PUT /v1/buckets/mozilla/groups/payments - "
             "403 Unauthorized. Please check that the "
             "bucket exists and that you have the permission "
diff --git a/kinto_http/tests/test_client.py b/kinto_http/tests/test_client.py
index 0d39af9..59ccf6a 100644
--- a/kinto_http/tests/test_client.py
+++ b/kinto_http/tests/test_client.py
@@ -1182,3 +1182,43 @@ class RecordTest(unittest.TestCase):
             permissions=None,
             headers=None,
         )
+
+
+class HistoryTest(unittest.TestCase):
+    def setUp(self):
+        self.session = mock.MagicMock()
+        self.client = Client(session=self.session)
+
+    def test_basic_retrivial_of_bucket_history(self):
+        mock_response(self.session)
+        self.client.get_history(bucket='mybucket')
+        url = '/buckets/mybucket/history'
+        self.session.request.assert_called_with('get', url, headers={}, params={})
+
+    def test_filter_sorting_operations_on_bucket_history(self):
+        mock_response(self.session)
+        self.client.get_history(bucket='mybucket',
+                                _limit=2,
+                                _sort='-last_modified',
+                                _since='1533762576015')
+
+        url = '/buckets/mybucket/history'
+        self.session.request.assert_called_with('get', url, headers={},
+                                                params={'_limit': 2,
+                                                        '_sort': '-last_modified',
+                                                        '_since': '1533762576015'}
+                                                )
+
+    def test_filtering_by_resource_name(self):
+        mock_response(self.session)
+        self.client.get_history(bucket='mybucket', resource_name='collection')
+        url = '/buckets/mybucket/history'
+        self.session.request.assert_called_with('get', url, headers={},
+                                                params={'resource_name': 'collection'}
+                                                )
+
+    def test_purging_of_history(self):
+        mock_response(self.session)
+        self.client.purge_history(bucket='mybucket')
+        url = '/buckets/mybucket/history'
+        self.session.request.assert_called_with('delete', url, headers=None)
diff --git a/kinto_http/tests/test_endpoints.py b/kinto_http/tests/test_endpoints.py
index 33d7898..52f27d2 100644
--- a/kinto_http/tests/test_endpoints.py
+++ b/kinto_http/tests/test_endpoints.py
@@ -38,6 +38,9 @@ class EndpointsTest(unittest.TestCase):
             == "/buckets/buck/collections/coll/records/1"
         )
 
+    def test_history(self):
+        assert self.endpoints.get("history", **self.kwargs) == "/buckets/buck/history"
+
     def test_missing_arguments_raise_an_error(self):
         # Don't include the record id; it should raise an error.
         with self.assertRaises(KintoException) as context:

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cache pytest-cov pytest-sugar pytest-xdist flake8
apt-get update apt-get install -y libffi-dev libssl-dev python3-dev
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
certifi==2019.6.16
chardet==3.0.4
coverage==7.8.0
exceptiongroup==1.2.2
execnet==2.1.1
flake8==7.2.0
idna==2.8
iniconfig==2.1.0
-e git+https://github.com/Kinto/kinto-http.py.git@83b66fbe9e037827cf0a77271d9c24ed50334b6d#egg=kinto_http
mccabe==0.7.0
packaging==24.2
pluggy==1.5.0
pycodestyle==2.13.0
pyflakes==3.3.2
pytest==8.3.5
pytest-cache==1.0
pytest-cov==6.0.0
pytest-sugar==1.0.0
pytest-xdist==3.6.1
requests==2.22.0
termcolor==3.0.0
tomli==2.2.1
Unidecode==1.1.1
urllib3==1.25.3

name: kinto-http.py
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - certifi==2019.6.16
      - chardet==3.0.4
      - coverage==7.8.0
      - exceptiongroup==1.2.2
      - execnet==2.1.1
      - flake8==7.2.0
      - idna==2.8
      - iniconfig==2.1.0
      - kinto-http==10.5.0.dev0
      - mccabe==0.7.0
      - packaging==24.2
      - pluggy==1.5.0
      - pycodestyle==2.13.0
      - pyflakes==3.3.2
      - pytest==8.3.5
      - pytest-cache==1.0
      - pytest-cov==6.0.0
      - pytest-sugar==1.0.0
      - pytest-xdist==3.6.1
      - requests==2.22.0
      - termcolor==3.0.0
      - tomli==2.2.1
      - unidecode==1.1.1
      - urllib3==1.25.3
prefix: /opt/conda/envs/kinto-http.py

kinto_http/tests/test_client.py::HistoryTest::test_basic_retrivial_of_bucket_history kinto_http/tests/test_client.py::HistoryTest::test_filter_sorting_operations_on_bucket_history kinto_http/tests/test_client.py::HistoryTest::test_filtering_by_resource_name kinto_http/tests/test_client.py::HistoryTest::test_purging_of_history kinto_http/tests/test_endpoints.py::EndpointsTest::test_history
kinto_http/tests/functional.py::FunctionalTest::test_bucket_creation kinto_http/tests/functional.py::FunctionalTest::test_bucket_creation_if_not_exists kinto_http/tests/functional.py::FunctionalTest::test_bucket_deletion kinto_http/tests/functional.py::FunctionalTest::test_bucket_deletion_if_exists kinto_http/tests/functional.py::FunctionalTest::test_bucket_modification kinto_http/tests/functional.py::FunctionalTest::test_bucket_retrieval kinto_http/tests/functional.py::FunctionalTest::test_bucket_retrieval_fails_when_not_created kinto_http/tests/functional.py::FunctionalTest::test_bucket_save kinto_http/tests/functional.py::FunctionalTest::test_bucket_sharing kinto_http/tests/functional.py::FunctionalTest::test_buckets_deletion kinto_http/tests/functional.py::FunctionalTest::test_buckets_deletion_when_no_buckets_exist kinto_http/tests/functional.py::FunctionalTest::test_buckets_retrieval kinto_http/tests/functional.py::FunctionalTest::test_collection_access_forbidden kinto_http/tests/functional.py::FunctionalTest::test_collection_creation kinto_http/tests/functional.py::FunctionalTest::test_collection_creation_if_not_exists kinto_http/tests/functional.py::FunctionalTest::test_collection_deletion kinto_http/tests/functional.py::FunctionalTest::test_collection_deletion_can_still_raise_errors kinto_http/tests/functional.py::FunctionalTest::test_collection_deletion_if_exists kinto_http/tests/functional.py::FunctionalTest::test_collection_list kinto_http/tests/functional.py::FunctionalTest::test_collection_not_found kinto_http/tests/functional.py::FunctionalTest::test_collection_sharing kinto_http/tests/functional.py::FunctionalTest::test_collections_deletion kinto_http/tests/functional.py::FunctionalTest::test_collections_deletion_when_no_collections_exist kinto_http/tests/functional.py::FunctionalTest::test_group_creation kinto_http/tests/functional.py::FunctionalTest::test_group_creation_if_bucket_does_not_exist kinto_http/tests/functional.py::FunctionalTest::test_group_creation_if_not_exists kinto_http/tests/functional.py::FunctionalTest::test_group_deletion kinto_http/tests/functional.py::FunctionalTest::test_group_deletion_can_still_raise_errors kinto_http/tests/functional.py::FunctionalTest::test_group_deletion_if_exists kinto_http/tests/functional.py::FunctionalTest::test_group_list kinto_http/tests/functional.py::FunctionalTest::test_group_update kinto_http/tests/functional.py::FunctionalTest::test_groups_deletion kinto_http/tests/functional.py::FunctionalTest::test_groups_deletion_when_no_groups_exist kinto_http/tests/functional.py::FunctionalTest::test_multiple_record_deletion kinto_http/tests/functional.py::FunctionalTest::test_one_record_deletion kinto_http/tests/functional.py::FunctionalTest::test_patch_record_jsonpatch kinto_http/tests/functional.py::FunctionalTest::test_record_creation_and_retrieval kinto_http/tests/functional.py::FunctionalTest::test_record_deletion_if_exists kinto_http/tests/functional.py::FunctionalTest::test_record_sharing kinto_http/tests/functional.py::FunctionalTest::test_records_deletion_when_no_records_exist kinto_http/tests/functional.py::FunctionalTest::test_records_generator_retrieval kinto_http/tests/functional.py::FunctionalTest::test_records_list_retrieval kinto_http/tests/functional.py::FunctionalTest::test_records_paginated_list_retrieval kinto_http/tests/functional.py::FunctionalTest::test_records_timestamp_retrieval kinto_http/tests/functional.py::FunctionalTest::test_replication kinto_http/tests/functional.py::FunctionalTest::test_request_batching kinto_http/tests/functional.py::FunctionalTest::test_single_record_can_overwrite kinto_http/tests/functional.py::FunctionalTest::test_single_record_creation_if_not_exists kinto_http/tests/functional.py::FunctionalTest::test_single_record_doesnt_overwrite kinto_http/tests/functional.py::FunctionalTest::test_single_record_save kinto_http/tests/functional.py::FunctionalTest::test_updating_data_on_a_collection kinto_http/tests/functional.py::FunctionalTest::test_updating_data_on_a_group
kinto_http/tests/test_client.py::ClientTest::test_auth_from_access_token kinto_http/tests/test_client.py::ClientTest::test_batch_does_not_raise_exception_if_batch_4xx_errors_are_ignored kinto_http/tests/test_client.py::ClientTest::test_batch_options_are_transmitted kinto_http/tests/test_client.py::ClientTest::test_batch_raises_exception kinto_http/tests/test_client.py::ClientTest::test_batch_raises_exception_if_subrequest_failed_with_code_4xx kinto_http/tests/test_client.py::ClientTest::test_batch_raises_exception_if_subrequest_failed_with_code_5xx kinto_http/tests/test_client.py::ClientTest::test_client_clone_with_auth kinto_http/tests/test_client.py::ClientTest::test_client_clone_with_auth_and_server_url kinto_http/tests/test_client.py::ClientTest::test_client_clone_with_auth_and_server_url_bucket_and_collection kinto_http/tests/test_client.py::ClientTest::test_client_clone_with_existing_session kinto_http/tests/test_client.py::ClientTest::test_client_clone_with_new_bucket_and_collection kinto_http/tests/test_client.py::ClientTest::test_client_clone_with_new_session kinto_http/tests/test_client.py::ClientTest::test_client_clone_with_server_url kinto_http/tests/test_client.py::ClientTest::test_client_is_represented_properly_with_bucket kinto_http/tests/test_client.py::ClientTest::test_client_is_represented_properly_with_bucket_and_collection kinto_http/tests/test_client.py::ClientTest::test_client_is_represented_properly_without_bucket kinto_http/tests/test_client.py::ClientTest::test_client_uses_default_bucket_if_not_specified kinto_http/tests/test_client.py::ClientTest::test_client_uses_passed_bucket_if_specified kinto_http/tests/test_client.py::ClientTest::test_context_manager_works_as_expected kinto_http/tests/test_client.py::ClientTest::test_server_info kinto_http/tests/test_client.py::BucketTest::test_bucket_names_are_slugified kinto_http/tests/test_client.py::BucketTest::test_create_bucket_can_deduce_id_from_data kinto_http/tests/test_client.py::BucketTest::test_delete_bucket_handles_if_match kinto_http/tests/test_client.py::BucketTest::test_delete_bucket_returns_the_contained_data kinto_http/tests/test_client.py::BucketTest::test_delete_is_issued_on_list_deletion kinto_http/tests/test_client.py::BucketTest::test_get_bucket_supports_queryparams kinto_http/tests/test_client.py::BucketTest::test_get_is_issued_on_list_retrieval kinto_http/tests/test_client.py::BucketTest::test_get_is_issued_on_retrieval kinto_http/tests/test_client.py::BucketTest::test_get_or_create_dont_raise_in_case_of_conflict kinto_http/tests/test_client.py::BucketTest::test_get_or_create_raise_in_other_cases kinto_http/tests/test_client.py::BucketTest::test_http_500_raises_an_error kinto_http/tests/test_client.py::BucketTest::test_patch_is_issued_on_patch kinto_http/tests/test_client.py::BucketTest::test_patch_requires_patch_to_be_patch_type kinto_http/tests/test_client.py::BucketTest::test_permissions_are_retrieved kinto_http/tests/test_client.py::BucketTest::test_put_is_issued_on_creation kinto_http/tests/test_client.py::BucketTest::test_put_is_issued_on_update kinto_http/tests/test_client.py::BucketTest::test_unauthorized_raises_a_kinto_exception kinto_http/tests/test_client.py::BucketTest::test_unexisting_bucket_raises kinto_http/tests/test_client.py::BucketTest::test_update_bucket_can_deduce_id_from_data kinto_http/tests/test_client.py::BucketTest::test_update_bucket_handles_if_match kinto_http/tests/test_client.py::GroupTest::test_create_group_can_deduce_id_from_data kinto_http/tests/test_client.py::GroupTest::test_create_group_raises_if_group_id_is_missing kinto_http/tests/test_client.py::GroupTest::test_patch_group_makes_request kinto_http/tests/test_client.py::GroupTest::test_patch_requires_patch_to_be_patch_type kinto_http/tests/test_client.py::GroupTest::test_update_group_can_deduce_id_from_data kinto_http/tests/test_client.py::GroupTest::test_update_group_raises_if_group_id_is_missing kinto_http/tests/test_client.py::CollectionTest::test_collection_can_be_deleted kinto_http/tests/test_client.py::CollectionTest::test_collection_can_delete_all_its_records kinto_http/tests/test_client.py::CollectionTest::test_collection_creation_issues_an_http_put kinto_http/tests/test_client.py::CollectionTest::test_collection_delete_if_match kinto_http/tests/test_client.py::CollectionTest::test_collection_delete_if_match_not_included_if_not_safe kinto_http/tests/test_client.py::CollectionTest::test_collection_names_are_slugified kinto_http/tests/test_client.py::CollectionTest::test_collection_update_issues_an_http_put kinto_http/tests/test_client.py::CollectionTest::test_collection_update_use_an_if_match_header kinto_http/tests/test_client.py::CollectionTest::test_create_collection_can_deduce_id_from_data kinto_http/tests/test_client.py::CollectionTest::test_create_collection_raises_a_special_error_on_403 kinto_http/tests/test_client.py::CollectionTest::test_data_can_be_sent_on_creation kinto_http/tests/test_client.py::CollectionTest::test_delete_is_issued_on_list_deletion kinto_http/tests/test_client.py::CollectionTest::test_get_collection_supports_queryparams kinto_http/tests/test_client.py::CollectionTest::test_get_collections_returns_the_list_of_collections kinto_http/tests/test_client.py::CollectionTest::test_get_or_create_doesnt_raise_in_case_of_conflict kinto_http/tests/test_client.py::CollectionTest::test_get_or_create_raise_in_other_cases kinto_http/tests/test_client.py::CollectionTest::test_patch_collection_handles_if_match kinto_http/tests/test_client.py::CollectionTest::test_patch_collection_issues_an_http_patch kinto_http/tests/test_client.py::CollectionTest::test_patch_requires_patch_to_be_patch_type kinto_http/tests/test_client.py::CollectionTest::test_update_collection_can_deduce_id_from_data kinto_http/tests/test_client.py::CollectionTest::test_update_handles_if_match kinto_http/tests/test_client.py::RecordTest::test_collection_argument_takes_precedence kinto_http/tests/test_client.py::RecordTest::test_collection_can_delete_a_record kinto_http/tests/test_client.py::RecordTest::test_collection_can_retrieve_all_records kinto_http/tests/test_client.py::RecordTest::test_collection_can_retrieve_records_timestamp kinto_http/tests/test_client.py::RecordTest::test_create_record_can_deduce_id_from_data kinto_http/tests/test_client.py::RecordTest::test_create_record_raises_a_special_error_on_403 kinto_http/tests/test_client.py::RecordTest::test_creation_doesnt_add_if_none_match_when_overwrite kinto_http/tests/test_client.py::RecordTest::test_creation_sends_if_none_match_by_default kinto_http/tests/test_client.py::RecordTest::test_data_and_permissions_are_added_on_create kinto_http/tests/test_client.py::RecordTest::test_generated_record_id_is_an_uuid kinto_http/tests/test_client.py::RecordTest::test_get_or_create_doesnt_raise_in_case_of_conflict kinto_http/tests/test_client.py::RecordTest::test_get_or_create_raise_in_other_cases kinto_http/tests/test_client.py::RecordTest::test_get_record_supports_queryparams kinto_http/tests/test_client.py::RecordTest::test_pagination_generator_if_none_match kinto_http/tests/test_client.py::RecordTest::test_pagination_is_followed kinto_http/tests/test_client.py::RecordTest::test_pagination_is_followed_for_number_of_pages kinto_http/tests/test_client.py::RecordTest::test_pagination_is_followed_generator kinto_http/tests/test_client.py::RecordTest::test_pagination_is_not_followed_if_limit_is_specified kinto_http/tests/test_client.py::RecordTest::test_pagination_supports_if_none_match kinto_http/tests/test_client.py::RecordTest::test_patch_record_recognizes_patchtype kinto_http/tests/test_client.py::RecordTest::test_patch_record_requires_data_to_be_patch_type kinto_http/tests/test_client.py::RecordTest::test_patch_record_requires_id kinto_http/tests/test_client.py::RecordTest::test_patch_record_understands_jsonpatch kinto_http/tests/test_client.py::RecordTest::test_patch_record_uses_the_patch_method kinto_http/tests/test_client.py::RecordTest::test_record_delete_if_match kinto_http/tests/test_client.py::RecordTest::test_record_delete_if_match_not_included_if_not_safe kinto_http/tests/test_client.py::RecordTest::test_record_id_is_derived_from_data_if_present kinto_http/tests/test_client.py::RecordTest::test_record_id_is_given_after_creation kinto_http/tests/test_client.py::RecordTest::test_record_issues_a_request_on_retrieval kinto_http/tests/test_client.py::RecordTest::test_records_handles_permissions kinto_http/tests/test_client.py::RecordTest::test_records_issues_a_request_on_delete kinto_http/tests/test_client.py::RecordTest::test_records_timestamp_is_cached kinto_http/tests/test_client.py::RecordTest::test_records_timestamp_is_cached_per_collection kinto_http/tests/test_client.py::RecordTest::test_update_record_can_deduce_id_from_data kinto_http/tests/test_client.py::RecordTest::test_update_record_gets_the_id_from_data_if_exists kinto_http/tests/test_client.py::RecordTest::test_update_record_handles_if_match kinto_http/tests/test_client.py::RecordTest::test_update_record_raises_if_no_id_is_given kinto_http/tests/test_endpoints.py::EndpointsTest::test_arguments_are_slugified kinto_http/tests/test_endpoints.py::EndpointsTest::test_batch kinto_http/tests/test_endpoints.py::EndpointsTest::test_bucket kinto_http/tests/test_endpoints.py::EndpointsTest::test_buckets kinto_http/tests/test_endpoints.py::EndpointsTest::test_collection kinto_http/tests/test_endpoints.py::EndpointsTest::test_collections kinto_http/tests/test_endpoints.py::EndpointsTest::test_missing_arguments_raise_an_error kinto_http/tests/test_endpoints.py::EndpointsTest::test_null_arguments_raise_an_error kinto_http/tests/test_endpoints.py::EndpointsTest::test_record kinto_http/tests/test_endpoints.py::EndpointsTest::test_records kinto_http/tests/test_endpoints.py::EndpointsTest::test_root
README.rst CHANGELOG.rst kinto_http/__init__.py
README.rst CHANGELOG.rst kinto_http/__init__.py