How To Restore A Document From An Older Revision
We all make mistakes. Sometimes our mistake is publishing a revision unintentionally with the Draft API. This guide demonstrates how to restore a document from an older revision.
Goals
At the end of this guide, a user will be able to load an arbitrary document revision and set it as the document’s draft and published revisions.
Prerequisites
- Knowledge of the following Draft API concepts:
- document
- revision
- draft vs published revision
- Experience with ANS
- Knowledge of HTTP, HTTP authentication, and cURL
Step-By-Step Guide
This guide starts with a circulated document that has been published.
Document:
{ "id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "draft_revision_id": "RGJV3JF7QRDRNM5FK22G3DAQZY", "published_revision_id": "XHPXJG22KRAF7H5USWLNFSPRDY", "first_published_at": "2019-09-25T12:36:51.278Z", "last_published_at": "2019-09-25T12:36:51.278Z", "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T12:36:51.19Z", "type": "STORY"}
Circulation:
{ "circulations": [ { "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "website_id": "testing", "website_url": "/2019/09/25/guide-title", "website_primary_section": { "type": "reference", "referent": { "type": "section", "id": "/programming", "website": "testing" } }, "website_sections": [ { "type": "reference", "referent": { "type": "section", "id": "/programming", "website": "testing" } } ] } ]}
Step 1: Edit Document without Publishing Changes
This step is a typical publisher workflow that involves editing and saving changes to a document without publishing. First, let’s retrieve the document’s draft revision for editing.
curl --request GET \ --header 'Authorization: Bearer <TOKEN>' \ --url https://api.{{org}}.arcpublishing.com/draft/v1/story/IXMKZP5SPVHKTJVGFF6FEGJECQ/revision/RGJV3JF7QRDRNM5FK22G3DAQZY
API response:
{ "id": "RGJV3JF7QRDRNM5FK22G3DAQZY", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "version": "0.10.2", "canonical_website": "testing", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T12:36:51.190Z", "headlines": { "basic": "Guide Title" }, "owner": { "id": "testing" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T12:36:51.19Z", "type": "DRAFT"}
Next, let’s edit the draft revision by changing headlines.basic
to Guide Edit 1
and saving it.
curl --request PUT \ --header 'Authorization: Bearer <TOKEN>' \ --url https://api.{{org}}.arcpublishing.com/draft/v1/story/IXMKZP5SPVHKTJVGFF6FEGJECQ/revision/draft \ --data '{ "ans": { "_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "type": "story", "version": "0.10.2", "canonical_website": "testing", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T12:36:51.190Z", "headlines": { "basic": "Guide Edit 1" }, "owner": { "id": "testing" } } }'
API response:
{ "id": "CY26R7VVJZFY5GCJLINJKUDZD4", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "version": "0.10.2", "canonical_website": "testing", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T13:08:21.296Z", "headlines": { "basic": "Guide Edit 1" }, "owner": { "id": "testing" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T13:08:21.296Z", "type": "DRAFT"}
When a draft revision is saved, a copy of the updated draft revision is returned. Notice that headlines.basic
reflects our change.
Next, let’s edit the draft revision again by changing headlines.basic
to Guide Edit 2
and saving it.
curl --request PUT \ --header 'Authorization: Bearer <TOKEN>' \ --url https://api.{{org}}.arcpublishing.com/draft/v1/story/IXMKZP5SPVHKTJVGFF6FEGJECQ/revision/draft \ --data '{ "ans": { "_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "type": "story", "version": "0.10.2", "canonical_website": "testing", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T13:08:21.296Z", "headlines": { "basic": "Guide Edit 2" }, "owner": { "id": "testing" } } }'
API response:
{ "id": "UWGSF5OJTNHX7EJRFUR44FMNQQ", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "version": "0.10.2", "canonical_website": "testing", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T13:18:24.392Z", "headlines": { "basic": "Guide Edit 2" }, "owner": { "id": "testing" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T13:18:24.392Z", "type": "DRAFT"}
Notice headlines.basic
reflects our change.
Saving a draft revision does not affect the published revision. Let’s verify this by retrieving the document’s published revision; the published revision’s id can be found at the top of the guide in the document JSON.
curl --request GET \ --header 'Authorization: Bearer <TOKEN>' \ --url https://api.{{org}}.arcpublishing.com/draft/v1/story/IXMKZP5SPVHKTJVGFF6FEGJECQ/revision/XHPXJG22KRAF7H5USWLNFSPRDY
API response:
{ "id": "XHPXJG22KRAF7H5USWLNFSPRDY", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "version": "0.10.2", "canonical_website": "testing", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T12:36:51.101Z", "headlines": { "basic": "Guide Title" }, "owner": { "id": "testing" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T12:36:51.101Z", "type": "PUBLISHED"}
Notice that headlines.basic
is still Guide Title
for the published revision.
Step 2: Publish Changes
This step publishes our most recently saved draft revision which has a headlines.basic
value of Guide Edit 2
.
curl --request POST \ --header 'Authorization: Bearer <TOKEN>' \ --url https://api.{{org}}.arcpublishing.com/draft/v1/story/IXMKZP5SPVHKTJVGFF6FEGJECQ/revision/published
API response:
{ "id": "YXGISUDDR5DAZKJV34YYTVVTAM", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "version": "0.10.2", "canonical_website": "testing", "created_date": "2019-09-25T12:26:07.201Z", "display_date": "2019-09-25T12:36:51.278Z", "publish_date": "2019-09-25T13:23:21.065Z", "first_publish_date": "2019-09-25T12:36:51.278Z", "last_updated_date": "2019-09-25T13:23:20.940Z", "headlines": { "basic": "Guide Edit 2" }, "owner": { "id": "testing" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T13:23:20.94Z", "type": "PUBLISHED"}
The Draft API returns the updated published revision when it is saved. Notice headlines.basic
reflects the title of our last saved draft revision.
Let’s retrieve the document to verify which revisions are set for draft and published.
curl --request GET \ --header 'Authorization: Bearer <TOKEN>' \ --url https://api.{{org}}.arcpublishing.com/draft/v1/story/IXMKZP5SPVHKTJVGFF6FEGJECQ
API response:
{ "id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "draft_revision_id": "V7XV2QVWDFEMZGFKBJVIOYQIME", "published_revision_id": "YXGISUDDR5DAZKJV34YYTVVTAM", "first_published_at": "2019-09-25T12:36:51.278Z", "last_published_at": "2019-09-25T13:23:21.065Z", "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T13:23:21.025Z", "type": "STORY"}
As expected, draft_revision_id
points to the last draft revision we saved in Step 1 and published_revision_id
points to the published revision returned during our publish action.
Step 3: Restore Previously Published Revision
But, wait! We didn’t mean to publish headline Guide Edit 2
! This step demonstrates how to find the previously published revision and restore it.
First, lets retrieve the list of revision summaries for the document.
curl --request GET \ --header 'Authorization: Bearer <TOKEN>' \ --url https://api.{{org}}.arcpublishing.com/draft/v1/story/IXMKZP5SPVHKTJVGFF6FEGJECQ/revision
API response:
{ "revisions": [ { "id": "ZGGUHWCIWRFRZOGQDBBKDNR55U", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T12:26:07.201Z", }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T12:26:07.201Z", "type": "DRAFT" }, { "id": "LRE2UKHEHJDQLN7IMPWTOACKZU", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T12:35:15.727Z", "headlines": { "basic": "Guide Title" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T12:35:15.727Z", "type": "DRAFT" }, { "id": "XHPXJG22KRAF7H5USWLNFSPRDY", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T12:36:51.101Z", "headlines": { "basic": "Guide Title" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T12:36:51.101Z", "type": "PUBLISHED" }, { "id": "RGJV3JF7QRDRNM5FK22G3DAQZY", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T12:36:51.190Z", "headlines": { "basic": "Guide Title" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T12:36:51.19Z", "type": "DRAFT" }, { "id": "3AKU4S7A6VCO5A44CEAJOLWVQ4", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T12:49:15.670Z", "headlines": { "basic": "Guide Title" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T12:49:15.67Z", "type": "PUBLISHED" }, { "id": "L57XAMA6GFDDLCWZP4HA6QJ2RA", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T12:49:15.930Z", "headlines": { "basic": "Guide Title" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T12:49:15.93Z", "type": "DRAFT" }, { "id": "CY26R7VVJZFY5GCJLINJKUDZD4", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T13:08:21.296Z", "headlines": { "basic": "Guide Edit 1" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T13:08:21.296Z", "type": "DRAFT" }, { "id": "UWGSF5OJTNHX7EJRFUR44FMNQQ", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T13:18:24.392Z", "headlines": { "basic": "Guide Edit 2" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T13:18:24.392Z", "type": "DRAFT" }, { "id": "YXGISUDDR5DAZKJV34YYTVVTAM", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T13:23:20.940Z", "headlines": { "basic": "Guide Edit 2" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T13:23:20.94Z", "type": "PUBLISHED" }, { "id": "V7XV2QVWDFEMZGFKBJVIOYQIME", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "created_date": "2019-09-25T12:26:07.201Z", "last_updated_date": "2019-09-25T13:23:21.025Z", "headlines": { "basic": "Guide Edit 2" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T13:23:21.025Z", "type": "DRAFT" } ]}
The revision summaries returned are sorted in ascending order by updated_at
. Draft revisions have a type
value of DRAFT
and published revisions have a type
value of PUBLISHED
.
At the end of Step 2, we saw that the current draft revision id is V7XV2QVWDFEMZGFKBJVIOYQIME
and the current published revision id is YXGISUDDR5DAZKJV34YYTVVTAM
. Notice that the last two items in the revision list are the current draft and published revisions.
The previously published revision can be found by walking up the revision list until we find the next revision where type = PUBLISHED
. Did you find revision with id = 3AKU4S7A6VCO5A44CEAJOLWVQ4
as the previous published revision? Notice that 3AKU4S7A6VCO5A44CEAJOLWVQ4
’s headlines.basic
is Guide Title
.
Now that we have the previous published revision’s ID, let’s restore it. First, we will need to retrieve the full revision.
curl --request GET \ --header 'Authorization: Bearer <TOKEN>' \ --url https://api.{{org}}.arcpublishing.com/draft/v1/story/IXMKZP5SPVHKTJVGFF6FEGJECQ/revision/3AKU4S7A6VCO5A44CEAJOLWVQ4
API response:
{ "id": "3AKU4S7A6VCO5A44CEAJOLWVQ4", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "version": "0.10.2", "canonical_website": "testing", "created_date": "2019-09-25T12:26:07.201Z", "display_date": "2019-09-25T12:36:51.278Z", "publish_date": "2019-09-25T12:36:51.278Z", "first_publish_date": "2019-09-25T12:36:51.278Z", "last_updated_date": "2019-09-25T12:49:15.670Z", "headlines": { "basic": "Guide Title" }, "owner": { "id": "testing" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T12:49:15.67Z", "type": "PUBLISHED"}
Next, let’s save the revision as the document’s draft revision.
curl --request PUT \ --header 'Authorization: Bearer <TOKEN>' \ --url https://api.{{org}}.arcpublishing.com/draft/v1/story/IXMKZP5SPVHKTJVGFF6FEGJECQ/revision/draft \ --data '{ "ans": { "_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "type": "story", "version": "0.10.2", "canonical_website": "testing", "created_date": "2019-09-25T12:26:07.201Z", "display_date": "2019-09-25T12:36:51.278Z", "publish_date": "2019-09-25T12:36:51.278Z", "first_publish_date": "2019-09-25T12:36:51.278Z", "last_updated_date": "2019-09-25T12:49:15.670Z", "headlines": { "basic": "Guide Title" }, "owner": { "id": "testing" } } }'
API response:
{ "id": "2J6G5YP5OFF5VAQMFJJTV7V2MQ", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "version": "0.10.2", "canonical_website": "testing", "created_date": "2019-09-25T12:26:07.201Z", "display_date": "2019-09-25T12:36:51.278Z", "publish_date": "2019-09-25T12:36:51.278Z", "first_publish_date": "2019-09-25T12:36:51.278Z", "last_updated_date": "2019-09-25T14:18:40.310Z", "headlines": { "basic": "Guide Title" }, "owner": { "id": "testing" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T14:18:40.31Z", "type": "DRAFT"}
Next, let’s publish the document.
curl --request POST \ --header 'Authorization: Bearer <TOKEN>' \ --url https://api.{{org}}.arcpublishing.com/draft/v1/story/IXMKZP5SPVHKTJVGFF6FEGJECQ/revision/published
API response:
{ "id": "GR4YBSWBZNDMNO354LCLR7CAX4", "document_id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "ans": { "type": "story", "version": "0.10.2", "canonical_website": "testing", "created_date": "2019-09-25T12:26:07.201Z", "display_date": "2019-09-25T12:36:51.278Z", "publish_date": "2019-09-25T14:20:28.014Z", "first_publish_date": "2019-09-25T12:36:51.278Z", "last_updated_date": "2019-09-25T14:20:27.910Z", "headlines": { "basic": "Guide Title" }, "owner": { "id": "testing" } }, "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T14:20:27.91Z", "type": "PUBLISHED"}
Finally, let’s retrieve the document and validate the published revision has changed.
curl --request GET \ --header 'Authorization: Bearer <TOKEN>' \ --url https://api.{{org}}.arcpublishing.com/draft/v1/story/IXMKZP5SPVHKTJVGFF6FEGJECQ
API response:
{ "id": "IXMKZP5SPVHKTJVGFF6FEGJECQ", "draft_revision_id": "AGWF2OWUEBFDNLBK56MT7ZC5OU", "published_revision_id": "GR4YBSWBZNDMNO354LCLR7CAX4", "first_published_at": "2019-09-25T12:36:51.278Z", "last_published_at": "2019-09-25T14:20:28.014Z", "created_at": "2019-09-25T12:26:07.201Z", "updated_at": "2019-09-25T14:20:27.968Z", "type": "STORY"}
Notice that the published_revision_id
points to the revision returned when we published the document. We have successfully restored the previously published revision.