diff --git a/openlobby/core/api/types.py b/openlobby/core/api/types.py
index a3d9966790f9ff7c3428c46f5da460b80c44afee..d0644aad3637d5cc491809c5a1d49dec4407163e 100644
--- a/openlobby/core/api/types.py
+++ b/openlobby/core/api/types.py
@@ -29,6 +29,8 @@ class Report(graphene.ObjectType):
     is_draft = graphene.Boolean()
     extra = JSONString()
     edited = graphene.String()
+    has_revisions = graphene.Boolean()
+    revisions = graphene.List(lambda: Report)
 
     class Meta:
         interfaces = (relay.Node,)
@@ -36,7 +38,7 @@ class Report(graphene.ObjectType):
     @classmethod
     def from_es(cls, report, author=None):
         return cls(
-            id=report.meta.id,
+            id=int(report.meta.id),
             author=author,
             date=report.date,
             published=report.published,
@@ -86,6 +88,15 @@ class Report(graphene.ObjectType):
         author = author_type.get_node(info, report.author_id)
         return cls.from_es(report, author)
 
+    def resolve_has_revisions(self, info, **kwargs):
+        return models.Report.objects.filter(superseded_by_id=self.id).count() > 0
+
+    def resolve_revisions(self, info, **kwargs):
+        revisions = models.Report.objects.filter(superseded_by_id=self.id).order_by(
+            "-edited"
+        )
+        return [Report.from_db(r) for r in revisions]
+
 
 class ReportConnection(relay.Connection):
     total_count = graphene.Int()
diff --git a/tests/dummy.py b/tests/dummy.py
index b0effcd184f4c422810e4d29c291c687fe0876d6..7d1570f95cb250d6bbad883f9006c12e2dec35ef 100644
--- a/tests/dummy.py
+++ b/tests/dummy.py
@@ -98,13 +98,12 @@ reports = [
         "date": arrow.get(2018, 1, 3).datetime,
         "published": arrow.get(2018, 1, 4).datetime,
         "edited": arrow.get(2018, 2, 1).datetime,
-        "title": "The Two Towers",
-        "body": "Another long story in progress.",
-        "received_benefit": "Mithrill Jacket",
-        "provided_benefit": "The Ring",
-        "our_participants": "Frodo, Gimli, Legolas",
-        "other_participants": "Saruman, Sauron",
-        "extra": {"rings": 2},
+        "title": "Oldest story",
+        "body": "Nothing yet.",
+        "received_benefit": "old bread",
+        "provided_benefit": "",
+        "our_participants": "",
+        "other_participants": "",
     },
     {
         "id": 7,
diff --git a/tests/mutations/snapshots/snap_test_update_report.py b/tests/mutations/snapshots/snap_test_update_report.py
index 70998a3972ffc1998324f3874498410cbb78b604..3c737e7876f465e271c65493ad782794c6eefbf9 100644
--- a/tests/mutations/snapshots/snap_test_update_report.py
+++ b/tests/mutations/snapshots/snap_test_update_report.py
@@ -102,6 +102,7 @@ snapshots['test_update_draft_with_draft 1'] = {
                 'date': '2018-03-03 00:00:00+00:00',
                 'edited': '2018-01-02 05:50:00+00:00',
                 'extra': None,
+                'hasRevisions': False,
                 'id': 'UmVwb3J0OjY2Ng==',
                 'isDraft': True,
                 'otherParticipants': 'grandchilds',
@@ -109,6 +110,8 @@ snapshots['test_update_draft_with_draft 1'] = {
                 'providedBenefit': 'water',
                 'published': '2018-01-02 05:50:00+00:00',
                 'receivedBenefit': 'cake',
+                'revisions': [
+                ],
                 'title': 'New title'
             }
         }
@@ -130,6 +133,7 @@ snapshots['test_update_draft_with_published 1'] = {
                 'date': '2018-03-03 00:00:00+00:00',
                 'edited': '2018-01-02 05:50:00+00:00',
                 'extra': None,
+                'hasRevisions': False,
                 'id': 'UmVwb3J0OjY2Ng==',
                 'isDraft': False,
                 'otherParticipants': 'grandchilds',
@@ -137,6 +141,8 @@ snapshots['test_update_draft_with_published 1'] = {
                 'providedBenefit': 'water',
                 'published': '2018-01-02 05:50:00+00:00',
                 'receivedBenefit': 'cake',
+                'revisions': [
+                ],
                 'title': 'New title'
             }
         }
@@ -158,6 +164,7 @@ snapshots['test_update_published_with_published 1'] = {
                 'date': '2018-03-03 00:00:00+00:00',
                 'edited': '2018-01-02 05:50:00+00:00',
                 'extra': None,
+                'hasRevisions': False,
                 'id': 'UmVwb3J0OjY2Ng==',
                 'isDraft': False,
                 'otherParticipants': 'grandchilds',
@@ -165,6 +172,8 @@ snapshots['test_update_published_with_published 1'] = {
                 'providedBenefit': 'water',
                 'published': '2018-01-02 00:00:00+00:00',
                 'receivedBenefit': 'cake',
+                'revisions': [
+                ],
                 'title': 'New title'
             }
         }
@@ -186,6 +195,7 @@ snapshots['test_input_sanitization 1'] = {
                 'date': '2018-03-03 00:00:00+00:00',
                 'edited': '2018-01-02 05:50:00+00:00',
                 'extra': None,
+                'hasRevisions': False,
                 'id': 'UmVwb3J0OjY2Ng==',
                 'isDraft': False,
                 'otherParticipants': 'you!',
@@ -193,6 +203,8 @@ snapshots['test_input_sanitization 1'] = {
                 'providedBenefit': 'tea',
                 'published': '2018-01-02 00:00:00+00:00',
                 'receivedBenefit': 'coffee',
+                'revisions': [
+                ],
                 'title': 'No tags'
             }
         }
@@ -214,6 +226,7 @@ snapshots['test_update_draft_with_draft__late_edit 1'] = {
                 'date': '2018-03-03 00:00:00+00:00',
                 'edited': '2018-01-02 06:10:00+00:00',
                 'extra': None,
+                'hasRevisions': False,
                 'id': 'UmVwb3J0OjY2Ng==',
                 'isDraft': True,
                 'otherParticipants': 'grandchilds',
@@ -221,6 +234,8 @@ snapshots['test_update_draft_with_draft__late_edit 1'] = {
                 'providedBenefit': 'water',
                 'published': '2018-01-02 06:10:00+00:00',
                 'receivedBenefit': 'cake',
+                'revisions': [
+                ],
                 'title': 'New title'
             }
         }
@@ -242,6 +257,7 @@ snapshots['test_update_draft_with_published__late_edit 1'] = {
                 'date': '2018-03-03 00:00:00+00:00',
                 'edited': '2018-01-02 06:10:00+00:00',
                 'extra': None,
+                'hasRevisions': False,
                 'id': 'UmVwb3J0OjY2Ng==',
                 'isDraft': False,
                 'otherParticipants': 'grandchilds',
@@ -249,6 +265,8 @@ snapshots['test_update_draft_with_published__late_edit 1'] = {
                 'providedBenefit': 'water',
                 'published': '2018-01-02 06:10:00+00:00',
                 'receivedBenefit': 'cake',
+                'revisions': [
+                ],
                 'title': 'New title'
             }
         }
@@ -365,6 +383,7 @@ snapshots['test_update_published_with_published__late_edit 1'] = {
                 'date': '2018-03-03 00:00:00+00:00',
                 'edited': '2018-01-02 06:10:00+00:00',
                 'extra': None,
+                'hasRevisions': True,
                 'id': 'UmVwb3J0OjY2Ng==',
                 'isDraft': False,
                 'otherParticipants': 'grandchilds',
@@ -372,6 +391,22 @@ snapshots['test_update_published_with_published__late_edit 1'] = {
                 'providedBenefit': 'water',
                 'published': '2018-01-02 00:00:00+00:00',
                 'receivedBenefit': 'cake',
+                'revisions': [
+                    {
+                        'body': 'Previous body.',
+                        'date': '2018-01-01 00:00:00+00:00',
+                        'edited': '2018-01-02 05:00:00+00:00',
+                        'extra': None,
+                        'id': '__STRIPPED__',
+                        'isDraft': False,
+                        'otherParticipants': 'grandma',
+                        'ourParticipants': 'grandpa',
+                        'providedBenefit': 'old tea',
+                        'published': '2018-01-02 00:00:00+00:00',
+                        'receivedBenefit': 'old coffee',
+                        'title': 'Original'
+                    }
+                ],
                 'title': 'New title'
             }
         }
diff --git a/tests/mutations/test_update_report.py b/tests/mutations/test_update_report.py
index 88a92e0ba548317e8d75ffd93654ef38d94c3ee0..d27d5bd991b6db404fe1104cf117ab4b824c4e68 100644
--- a/tests/mutations/test_update_report.py
+++ b/tests/mutations/test_update_report.py
@@ -27,6 +27,21 @@ mutation updateReport ($input: UpdateReportInput!) {
             isDraft
             extra
             edited
+            hasRevisions
+            revisions {
+                id
+                date
+                published
+                title
+                body
+                receivedBenefit
+                providedBenefit
+                ourParticipants
+                otherParticipants
+                isDraft
+                extra
+                edited
+            }
             author {
                 id
                 firstName
@@ -171,6 +186,7 @@ def test_update_published_with_published__late_edit(
     with patch("openlobby.core.api.mutations.arrow.utcnow", return_value=late_edited):
         response = call_api(query, input, original_report.author)
 
+    strip_value(response, "data", "updateReport", "report", "revisions", "id")
     snapshot.assert_match(response)
     assert Report.objects.count() == 2
     updated = Report.objects.filter(id=original_report.id).values()[0]
diff --git a/tests/schema/snapshots/snap_test_node.py b/tests/schema/snapshots/snap_test_node.py
index 161f827aabd03a99f0ec40e5bb27acfc04c5d748..2988f730c1330ee1276292fca6b3e6eb5ddd9da8 100644
--- a/tests/schema/snapshots/snap_test_node.py
+++ b/tests/schema/snapshots/snap_test_node.py
@@ -109,3 +109,65 @@ snapshots['test_report__is_draft 1'] = {
         }
     }
 }
+
+snapshots['test_report__without_revisions 1'] = {
+    'data': {
+        'node': {
+            'hasRevisions': False,
+            'id': 'UmVwb3J0OjM=',
+            'revisions': [
+            ],
+            'title': 'The Return of the King'
+        }
+    }
+}
+
+snapshots['test_report__with_revisions 1'] = {
+    'data': {
+        'node': {
+            'body': 'Another long story.',
+            'date': '2018-01-03 00:00:00+00:00',
+            'edited': '2018-01-04 05:00:00+00:00',
+            'extra': '{"rings": 1}',
+            'hasRevisions': True,
+            'id': 'UmVwb3J0OjI=',
+            'isDraft': False,
+            'otherParticipants': 'Saruman, Sauron',
+            'ourParticipants': 'Frodo, Gimli, Legolas',
+            'providedBenefit': '',
+            'published': '2018-01-04 00:00:00+00:00',
+            'receivedBenefit': 'Mithrill Jacket',
+            'revisions': [
+                {
+                    'body': 'What am I doing?',
+                    'date': '2018-01-03 00:00:00+00:00',
+                    'edited': '2018-02-05 00:00:00+00:00',
+                    'extra': '{"rings": 1}',
+                    'id': 'UmVwb3J0Ojc=',
+                    'isDraft': False,
+                    'otherParticipants': '',
+                    'ourParticipants': 'Ringo Starr',
+                    'providedBenefit': 'The Ringo',
+                    'published': '2018-01-04 00:00:00+00:00',
+                    'receivedBenefit': 'Jacket',
+                    'title': 'The Towels'
+                },
+                {
+                    'body': 'Nothing yet.',
+                    'date': '2018-01-03 00:00:00+00:00',
+                    'edited': '2018-02-01 00:00:00+00:00',
+                    'extra': None,
+                    'id': 'UmVwb3J0OjY=',
+                    'isDraft': False,
+                    'otherParticipants': '',
+                    'ourParticipants': '',
+                    'providedBenefit': '',
+                    'published': '2018-01-04 00:00:00+00:00',
+                    'receivedBenefit': 'old bread',
+                    'title': 'Oldest story'
+                }
+            ],
+            'title': 'The Two Towers'
+        }
+    }
+}
diff --git a/tests/schema/snapshots/snap_test_search_reports.py b/tests/schema/snapshots/snap_test_search_reports.py
index b7f149099de1021e8951fc21bc6694ba1b4883ca..958d01e0faea60ce4117c2382cbe94712fda67ad 100644
--- a/tests/schema/snapshots/snap_test_search_reports.py
+++ b/tests/schema/snapshots/snap_test_search_reports.py
@@ -26,6 +26,7 @@ snapshots['test_all 1'] = {
                         'date': '2018-01-05 00:00:00+00:00',
                         'edited': '2018-01-06 07:00:00+00:00',
                         'extra': None,
+                        'hasRevisions': False,
                         'id': 'UmVwb3J0OjM=',
                         'isDraft': False,
                         'otherParticipants': 'Sauron',
@@ -51,6 +52,7 @@ snapshots['test_all 1'] = {
                         'date': '2018-01-03 00:00:00+00:00',
                         'edited': '2018-01-04 05:00:00+00:00',
                         'extra': '{"rings": 1}',
+                        'hasRevisions': True,
                         'id': 'UmVwb3J0OjI=',
                         'isDraft': False,
                         'otherParticipants': 'Saruman, Sauron',
@@ -76,6 +78,7 @@ snapshots['test_all 1'] = {
                         'date': '2018-01-01 00:00:00+00:00',
                         'edited': '2018-01-02 03:00:00+00:00',
                         'extra': None,
+                        'hasRevisions': True,
                         'id': 'UmVwb3J0OjE=',
                         'isDraft': False,
                         'otherParticipants': 'Saruman',
@@ -117,6 +120,7 @@ snapshots['test_query 1'] = {
                         'date': '2018-01-03 00:00:00+00:00',
                         'edited': '2018-01-04 05:00:00+00:00',
                         'extra': '{"rings": 1}',
+                        'hasRevisions': True,
                         'id': 'UmVwb3J0OjI=',
                         'isDraft': False,
                         'otherParticipants': 'Saruman, Sauron',
@@ -152,6 +156,7 @@ snapshots['test_highlight 1'] = {
                         'date': '2018-01-05 00:00:00+00:00',
                         'edited': '2018-01-06 07:00:00+00:00',
                         'extra': None,
+                        'hasRevisions': False,
                         'id': 'UmVwb3J0OjM=',
                         'isDraft': False,
                         'otherParticipants': 'Sauron',
@@ -177,6 +182,7 @@ snapshots['test_highlight 1'] = {
                         'date': '2018-01-01 00:00:00+00:00',
                         'edited': '2018-01-02 03:00:00+00:00',
                         'extra': None,
+                        'hasRevisions': True,
                         'id': 'UmVwb3J0OjE=',
                         'isDraft': False,
                         'otherParticipants': 'Saruman',
diff --git a/tests/schema/test_node.py b/tests/schema/test_node.py
index c386a6a3ca079915070e35882d5c5865c90e4a11..4e1984caa17e872ef3d44d0ae86c73f751861b70 100644
--- a/tests/schema/test_node.py
+++ b/tests/schema/test_node.py
@@ -160,6 +160,71 @@ def test_report__is_draft__viewer_is_not_author(client, snapshot):
     snapshot.assert_match(response)
 
 
+def test_report__without_revisions(client, snapshot):
+    prepare_reports()
+    query = """
+    query {{
+        node (id:"{id}") {{
+            ... on Report {{
+                id
+                title
+                hasRevisions
+                revisions {{
+                    id
+                }}
+            }}
+        }}
+    }}
+    """.format(
+        id=to_global_id("Report", 3)
+    )
+    response = call_api(client, query)
+    snapshot.assert_match(response)
+
+
+def test_report__with_revisions(client, snapshot):
+    prepare_reports()
+    query = """
+    query {{
+        node (id:"{id}") {{
+            ... on Report {{
+                id
+                date
+                published
+                title
+                body
+                receivedBenefit
+                providedBenefit
+                ourParticipants
+                otherParticipants
+                isDraft
+                extra
+                edited
+                hasRevisions
+                revisions {{
+                    id
+                    date
+                    published
+                    title
+                    body
+                    receivedBenefit
+                    providedBenefit
+                    ourParticipants
+                    otherParticipants
+                    isDraft
+                    extra
+                    edited
+                }}
+            }}
+        }}
+    }}
+    """.format(
+        id=to_global_id("Report", 2)
+    )
+    response = call_api(client, query)
+    snapshot.assert_match(response)
+
+
 def test_user__unauthorized(client, snapshot):
     User.objects.create(
         id=8,
diff --git a/tests/schema/test_search_reports.py b/tests/schema/test_search_reports.py
index b3ac2d75546f5bc79b842ee2efa246f76f4d115e..910b80d64ef2f9072b194fe56b621f1ebac9c870 100644
--- a/tests/schema/test_search_reports.py
+++ b/tests/schema/test_search_reports.py
@@ -28,6 +28,7 @@ def test_all(client, snapshot):
                     isDraft
                     extra
                     edited
+                    hasRevisions
                     author {
                         id
                         firstName
@@ -72,6 +73,7 @@ def test_query(client, snapshot):
                     isDraft
                     extra
                     edited
+                    hasRevisions
                     author {
                         id
                         firstName
@@ -110,6 +112,7 @@ def test_highlight(client, snapshot):
                     isDraft
                     extra
                     edited
+                    hasRevisions
                     author {
                         id
                         firstName
diff --git a/tests/utils.py b/tests/utils.py
index f214c05cbc902bf4683f360634693dd3c2e0d3aa..ca15876585e45fc1db0a483882b765d50be8c563 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -26,7 +26,12 @@ def strip_value(data, *path):
         data[element] = "__STRIPPED__"
         return value
     else:
-        return strip_value(value, *path[1:])
+        if isinstance(value, dict):
+            return strip_value(value, *path[1:])
+        elif isinstance(value, list):
+            return [strip_value(item, *path[1:]) for item in value]
+        else:
+            raise NotImplementedError()
 
 
 def dates_to_iso(data):