Skip to content
Product Documentation

Getting Started with the Draft API

After you read this guide, you’ll be able to use the Draft API to create, edit, publish, and circulate a document without leaving your command line.

This guide is an introduction to the Draft API for the purpose of creating and updating documents.

Requirements

You should:

  • Know what HTTP is
  • Have a general sense of what an API is

All other concepts are explained throughout the guide.

Authentication

To access the API, you need an access token. Please follow Accessing the Arc XP APIs guide to obtain one. In the rest of this document, when you see <TOKEN>, this refers to your access token, and you should replace <TOKEN> with the value of your token.

General Concepts

In this section, we introduce some important concepts of the Draft API.

Document

In general, a document can be understood as “a piece of content”. A document can be a story, an image, or a video. All documents share the following common attributes:

  • A unique identifier (ID) - a string of characters and numbers, like OXSDHY3JOFFCFKJUVGEPUB77YQ, that lets you uniquely identify and find the content within your organization.
  • A type - states whether this document is a story, an image, or a video.
  • A couple dates - the typical creation date and the date the document was last updated.
  • Revisions - one or more versions of your document, in chronological order.

The Draft API is for only story documents. Use the Photo Center API to work with image and gallery documents. Use the Video Center API to work with video documents.

Revisions

Every time you save a document, you create a new revision or version, depending on how you want to think about it. In the rest of this document, we use the term revision. Like documents, revisions have a number of common attributes:

  • They belong to a document. Each revision is associated with a single document, and each document can have one or multiple revisions.
  • They are immutable. After a revision is created, it can never be changed. This is important for history, caching, etc. If for any reason you want to change a revision (say you found a typo), then you must create a new revision.
  • They have a unique identifier. Because revisions are immutable, they receive their own identifier. The identifier format is the same as the identifier that documents use. It is guaranteed to be unique across the organization.
  • They have a type. The type should be the same as the document’s type: story, image, video, etc.
  • They hold content, in the form of an ANS Document.

Publication model

Documents are made of two mutually exclusive sets of a draft revision and published revision. When creating a document, you must supply a draft revision. As you work with your document, it reaches a ready state, and you want to publish it. When you do, a copy of the current draft is created, and it becomes a new published revision. That new published revision is then cloned, and it becomes the current draft (more on that later in the guide). The following illustration shows this process:

Publication Model

Let’s describe what happens:

  1. The document is created on 2019-09-01. At this time, the document contains one draft revision and no published revision.
  2. On 2019-09-02, a second draft is created. The user updated the document with content, maybe a title, text, and metadata.
  3. The next day, on 2019-09-03, the user decides that their work is ready for publishing. They publish the current draft (OHYE3MUS). Publishing the current draft creates a copy of the revision (TITEE2YI). This new revision becomes the first published revision. The published revision is then copied and becomes the new draft (HOH6AIG8).
  4. The user makes some additional changes, and creates a new draft revision on 2019-09-04 (PHIA0AEK).
  5. The previous changes to the document are important, and the user decides to publish them. To do so, they call the publish endpoints, which again copies the current draft to create a new published revision (XA4IS6TH). A new draft is created as well (ZOOV1HAH).
  6. A final modification is made to the document, which creates a new draft revision (NE3AIKOO). This draft revision is not published.

A few comments:

  • When you publish a document, a copy of the current draft revision is created and saved as the current published revision.
  • As a result, a published revision always has a counterpart (as in, a clone) in the draft revision set. It is not possible to publish a revision that has not first been a draft.1
  • After a new published revision has been created, it is copied back as the new current draft. This is to ensure that the “last update” date of the “draft” branch is always after the “last update” date of the “published” branch. This way, there is never any confusion as to which version of the content is “latest”. The current draft is always the “latest” version of the document (though, of course, it may not reflect what is currently published on the web).

In the rest of this document, this schema will be reused to illustrate what happens as API calls are made.

Circulations

Working with a document is great, but ultimately you want to publish it on the web. In Arc XP, an organization is comprised of several websites. And each website can have multiple sections:

Circulations

Circulations, together, define:

  • Which websites a document can appear on
  • Which website is the primary website (aka canonical)
  • The URL of the document on each website
  • For each website, which sections the document can appear in
  • For the primary website, which section is primary

Circulations 2

In the schema above, the document:

  • Appears on 2 websites, the-river-post and cyclist-daily
  • the-river-post is the primary website
  • Is not present/circulated on the website rivercitynews

On the-river-post:

  • It has the URL /news/<date>/parade
  • It belongs to the section /news, which is the primary section
  • It also belongs to the section /the-city

On cyclist-daily:

  • It has the URL /wheels-news/<date>/parade
  • It belongs to the section /wheels-news
  • It does not belong to any other section

Circulations and Revisions

It is important to note that creating/updating/deleting the circulation of a document does not change or affect its revision:

  • Revisions are about content
  • Circulations are about distribution

In particular, you can create a circulation for a document before it is published. This, in itself, will not publish the document. Once the document is published, however, it will show on the websites & sections defined by the circulations.

Creating a new document

Creating a new document requires you to provide initial valid ANS:

Terminal window
curl --request POST \
--header 'Authorization: Bearer <TOKEN>' \
--header 'Content-Type: application/json' \
--url https://api.{{org}}.arcpublishing.com/draft/v1/story \
--data '{
"type": "story",
"version": "0.10.10",
"canonical_website": "cyclist-daily",
"headlines": {
"basic": "My new story"
}
}'

You will get the same response back (for example, the document):

{
"id": "ZHXE3Y6OJVAUFDJIM3M43AV5KM",
"draft_revision_id": "EQFXJDR4CJDGPKCN7PA4G3UMAQ",
"created_at": "2019-09-01T09:00:00Z",
"type": "STORY"
}

You can view the revision by making the following request:

Terminal window
curl --request GET \
--header 'Authorization: Bearer <TOKEN>' \
--url https://api.{{org}}.arcpublishing.com/draft/v1/story/ZHXE3Y6OJVAUFDJIM3M43AV5KM/revision

Response:

{
"revisions": [
{
"type": "DRAFT", // Draft or published
"id": "EQFXJDR4CJDGPKCN7PA4G3UMAQ", // Revision ID
"document_id": "ZHXE3Y6OJVAUFDJIM3M43AV5KM", // Document ID
"created_at": "2019-09-01T09:00:00Z", // Creation date
"ans": { // Content of the revision
"version": "0.10.10", // ANS - Version
"type": "story", // ANS - Document type
"created_date": "2019-09-01T09:00:00Z", // ANS - Creation date
"last_updated_date": "2019-09-01T09:00:00Z", // ANS - Updated at date (= creation)
"headlines": { // ++ Added
"basic": "My new story" // ++ Added
} // ++ Added
}
}
]
}

Validating the document

You can validate a document’s ANS using this POST endpoint in the ANS service:

Terminal window
curl --request POST \
--url https://api.{{org}}.arcpublishing.com/ans/validate/{{ans version}} \
--header 'Authorization: Bearer <TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"canonical_website": "test-website",
"headlines": {
"basic": "Test Document",
"meta_title": "Adding meta title"
},
"owner": {
"id": {{org}}
},
"type": "story",
"version": "{{ans version}}",
"slug": "testDocument",
"revision": {
"user_id": "test_user"
}
}'

Use the same {{ans version}} as the document’s ans.version key in the URL path of the endpoint. For example, if your document is "version": "0.10.10", then the endpoint is https://api.{{org}}.arcpublishing.com/ans/validate/0.10.10.

If the document ANS is valid, the endpoint returns true.

Looking at the document

You can get the document back using the GET endpoint:

Terminal window
curl --request GET \
--header 'Authorization: Bearer <TOKEN>' \
--url https://api.{{org}}.arcpublishing.com/draft/v1/story/ZHXE3Y6OJVAUFDJIM3M43AV5KM
# This returns a `Document` object

You can also get the list of revisions (added /revision):

Terminal window
curl --request GET \
--header 'Authorization: Bearer <TOKEN>' \
--url https://api.{{org}}.arcpublishing.com/draft/v1/story/ZHXE3Y6OJVAUFDJIM3M43AV5KM/revision
# This returns a list of revision summaries:
# [
# revision summary,
# revision summary,
# revision summary,
# ...
# ]

Response:

{
"revisions": [
{
"type": "DRAFT", // Draft or published
"id": "EQFXJDR4CJDGPKCN7PA4G3UMAQ", // Revision ID
"document_id": "ZHXE3Y6OJVAUFDJIM3M43AV5KM", // Document ID
"created_at": "2019-09-01T09:00:00Z", // Creation date
"ans": { // Content of the revision
"version": "0.10.10", // ANS - Version
"type": "story", // ANS - Document type
"created_date": "2019-09-01T09:00:00Z", // ANS - Creation date
"last_updated_date": "2019-09-01T09:00:00Z" // ANS - Updated at date (= creation)
}
}
]
}

So at this point, the document looks like this:

Validation

Updating the document

Updating the document is just as easy: simply provide the ANS.

Terminal window
curl --request PUT \
--header 'Authorization: Bearer <TOKEN>' \
--header 'Content-Type: application/json' \
--url https://api.{{org}}.arcpublishing.com/draft/v1/story/ZHXE3Y6OJVAUFDJIM3M43AV5KM/revision/draft \
--data '{
"ans": {
"_id": "ZHXE3Y6OJVAUFDJIM3M43AV5KM",
"type": "story",
"version": "0.10.10",
"canonical_website": "cyclist-daily",
"headlines": {
"basic": "My updated story (v2)"
}
}
}'

For creating a document, POST /draft/v1/story was called. To update the document, you will create a new draft revision. The call now looks like this: PUT /draft/v1/story/ID/revision/draft. This can be decomposed like so:

/draft # root (or base path)
/v1 # current version of the API
/story # the content type (story, video, image, ...)
/ID # the document ID
/revision # the document sub-resource
/draft # type of revision

You can do a 3rd update, just the same way (updated headline):

Terminal window
curl --request PUT \
--header 'Authorization: Bearer <TOKEN>' \
--header 'Content-Type: application/json' \
--url https://api.{{org}}.arcpublishing.com/draft/v1/story/ZHXE3Y6OJVAUFDJIM3M43AV5KM/revision/draft \
--data '{
"ans": {
"_id": "ZHXE3Y6OJVAUFDJIM3M43AV5KM",
"type": "story",
"version": "0.10.10",
"canonical_website": "cyclist-daily",
"headlines": {
"basic": "My updated story (v3)"
}
}
}'

The document now looks like this:

Document update

The document is ready to be published. There are 2 things left to do:

  • Define its circulation
  • Publish it

Circulating the document

The story is important, so it’s going to be circulated on more than 1 section/website. Just like the examples before, the document will be circulated to 2 websites and 3 sections. We’ll pick /news on river-city-post to be the primary section:

Terminal window
# First website
curl --request PUT \
--header 'Authorization: Bearer <TOKEN>' \
--header 'Content-Type: application/json' \
--url https://api.{{org}}.arcpublishing.com/draft/v1/story/ZHXE3Y6OJVAUFDJIM3M43AV5KM/circulation/river-city-post \
--data '{
"document_id": "ZHXE3Y6OJVAUFDJIM3M43AV5KM",
"website_id": "river-city-post",
"website_url": "/news/2019/09/04/parade",
"website_primary_section": {
"type": "reference",
"referent": {
"id": "/news",
"type": "section",
"website": "river-city-post"
}
},
"website_sections": [
{
"type": "reference",
"referent": {
"id": "/news",
"type": "section",
"website": "river-city-post"
}
},
{
"type": "reference",
"referent": {
"id": "/the-city",
"type": "section",
"website": "river-city-post"
}
}
]
}'
Terminal window
# Second website
curl --request PUT \
--header 'Authorization: Bearer <TOKEN>' \
--header 'Content-Type: application/json' \
--url https://api.{{org}}.arcpublishing.com/draft/v1/story/ZHXE3Y6OJVAUFDJIM3M43AV5KM/circulation/cyclist-daily \
--data '{
"document_id": "ZHXE3Y6OJVAUFDJIM3M43AV5KM",
"website_id": "cyclist-daily",
"website_url": "/wheels-news/2019/09/04/parade",
"website_primary_section": {
"type": "reference",
"referent": {
"id": "/wheels-news",
"type": "section",
"website": "cyclist-daily"
}
},
"website_sections": [
{
"type": "reference",
"referent": {
"id": "/wheels-news",
"type": "section",
"website": "cyclist-daily"
}
}
]
}'

The document now looks like this:

Circulations

Looking up circulations

You can easily check the current circulations (with a ‘s’, since circulations are per website):

Terminal window
# 1st website
curl --request GET \
--header 'Authorization: Bearer <TOKEN>' \
--url https://api.{{org}}.arcpublishing.com/draft/v1/story/ZHXE3Y6OJVAUFDJIM3M43AV5KM/circulation/river-city-post
# 2nd website
curl --request GET \
--header 'Authorization: Bearer <TOKEN>' \
--url https://api.{{org}}.arcpublishing.com/draft/v1/story/ZHXE3Y6OJVAUFDJIM3M43AV5KM/circulation/cyclist-daily

Publishing the document

The document is ready to be published. Let’s go ahead:

Terminal window
curl --request POST \
--header 'Authorization: Bearer <TOKEN>' \
--header 'Content-Type: application/json' \
--url https://api.{{org}}.arcpublishing.com/draft/v1/story/ZHXE3Y6OJVAUFDJIM3M43AV5KM/revision/published \

Let’s look at the document now:

publishing

Publishing the document did the following:

  • It created a copy of the current draft revision (U633XTDDY...IPH7CAHS...)
  • It published the newly created revision (IPH7CAHS...)
  • It made a copy of the published revision and set it as the new draft revision (AHDAHB9D...)

The document is now both published and circulated. Let the readers come!

Leveraging the Arc-Priority HTTP header

The Draft API leverages an HTTP header, Arc-Priority, to segment content that authors are actively working on from historical content. The Arc-Priority header allows for two values: standard and ingestion.

Always use the ingestion header when ingesting historical content, like when you’re moving from an old CMS to Arc XP. Don’t use the standard header when migrating. Use the standard header only if you’re ingesting current content into Arc XP that was authored in an external CMS that day. This is not a common use of the Arc XP APIs.

Setting the priority for migrated and legacy content to ingestion ensures that legacy content does not crowd out content your organization produces within Composer. Failure to use this header could lead to stale content on your site.

Note that content in the ingestion lane is not sent to WebSked and is therefore not available to be added to Collections.

When interacting with the Draft API to manage ingested content (legacy or automated), you must add the following header: Arc-Priority: ingestion.

If you have an IFX integration listening for story:update and are performing programmatic updates, include header Arc-Priority: ingestion; IFX will ignore this message and it prevents an infinite loop.


Footnotes

  1. This is not always true for content created outside of Draft API, as other systems may not enforce this workflow.