Published or Draft?

Hi @gabriel!

That’s unfortunate as you say, it would be a good piece of information to have in the preview api. Would it be worth making this into an enhancement?

Thanks for the answer


Hey @christian.kissner,

I think there are some big considerations in implenting this, but our product team is already aware of your great feedback and I’ll update this thread in case it changes :blush:

Let me know if you have any other questions :slight_smile:

1 Like

Great, thanks!

Adding sys.publishedVersion to the response should be good enough since sys.version is already present.


1 Like

Hi @christian.kissner, you also could accomplish this by making a CDA call which might be easier, faster, and you wouldn’t be exposing a CMA token.

Query for entries and filter by the of the entry in question:<SPACE_ID>/entries?<ENTRY.SYS.ID> and if the resulting response.items is empty (i.e., length is zero) it means the entry in question is draft. If the resulting response.items has one item and the sys.updatedAt properties of the CDA and CPA responses are the same this means the entry is published, and the sys.updatedAt properties are different this means the entry is published with pending changes. Here’s a table of the different statuses:

CDA & CPA sys.updatedAt same CDA & CPA sys.updatedAt different
response.items = 0 draft draft
response.items = 1 published published with pending changes

How does your preview frontend use this information? Normally users don’t really care if an entry is draft or published when previewing because they are editing a specific page, article, or post, etc. in Contentful and the preview link in the webapp links directly to the preview app’s view of that specific piece of content. I could see this information being helpful if a field value isn’t passing that field’s validation rules (which could happen with draft or updated entries) but this could also be mitigated with error handling in the frontend app.


Hi Charlie, thanks for looking into this!

Rather than sending users to the contentful CMS app first, we’d like to send them to the preview site directly so they get more of a WYSIWYG experience. We’d just inject edit icons that link to the contentful CMS app. In the screenshot below the red box alerts
the user that the entry hasn’t been published yet. Please excuse the design, it’s actually been replaced a few years back.

There certainly are workarounds for the missing draft status info in the preview API. And if you’re only looking at it in the context of the custom preview integration within the contentful cms app there’s of course no point. But there are other use cases.


1 Like

Thanks for the context around what you are trying to do. I’ll certainly share your feedback with our product team and see if that might be something they’d add.

In the meantime you can use a small variation of what I suggested above to achieve the same result. I don’t know how exactly you are querying Contentful for the content on the example page you shared, but essentially you get a list of entries from the Preview API and make a list of the entry IDs and then query the Delivery API for entries where the is in that list (e.g., /entries?[in]=2lBPK3dEm84YOGIGUkEAi,1tnuVuJ6KUk84GMGGKoo68,1jteZMOi8eIoAQQWGOwIQy). The entry IDs that are only in the preview list are draft, ones that are in both lists and the sys.updatedAt property is the same are published and ones that are in both lists and the sys.updatedAt property is different are updated.

Here is a little javascript function I wrote to put a sys.status property on the list of entries:

function setEntryStatus(response) {
  let cpa_entries = response.items
  const cda_client = contentful.createClient({
    space: 'process.env.SPACE_ID',
    accessToken: 'process.env.CDA_TOKEN'
  let cpa_ids = cpa_entries.reduce((a, c) => `${a}${a ? ',' : ''}${}`, '')
  return cda_client.getEntries({'[in]': cpa_ids}).then(response => {
    let cda_entries = response.items
    for (entry of cpa_entries) {
      let cda_entry = cda_entries.filter(i => ==[0]
      if (cda_entry) {
        if (cda_entry.sys.updatedAt == entry.sys.updatedAt) {
          entry.sys.status = 'published'
        } else if (cda_entry.sys.updatedAt != entry.sys.updatedAt) {
          entry.sys.status = 'updated'
      } else {
        entry.sys.status = 'draft'
    return cpa_entries

Then you can use it like so:

var entries = []
preview_client.getEntries().then(setEntryStatus).then((items) => { 
  entries = items; 
  // now each entry will have a sys.status property

This would result in one extra CDA call but then you’d have a sys.status property that could determine the visibility of the edit icons.

hope this helps!


@charlie, @gabriel – Thank you for providing these workarounds / solutions. I would also argue that the CPA (not just the Management API) should tell us if an entry has unpublished edits or not, and further more allow us filter by this info. Contentful UI allows us to filter entries by their status (i.e. Published, Changed, Draft, & Archived). I can’t think of why this info should not be returned by CPA.

I’d like to know if you have any suggestions for a problem I am trying to solve: I am trying to get a list of entries that are in the Changed or Draft state. We could have hundreds of published entries, however only a small number of them would be in the Changed or Draft state.

Going with the workaround you suggested means I would have to first make two API calls (one against CDA and one again CPA) requesting only the sys.updatedAt field for all entries in our space, compare the two list to come up with the small subset entries, and finally make a 3rd call against CPA to fetch the contents.
Using Management API would have other consequences (a second set of SDK to load, using a token that’s tied to a user, etc.).

Thank you


What if an entry is in draft status because it has been unpublished or unarchived? Is there a way to fetch the unpublished or unarchived date?

This is so strange, so to know which items of a content_type that are draft i have to fetch all entries in the preview API then fetch all items in the delivery API and map over them to see which are missing in the delivery API response? I’m sorry but what?


Both of these can be determined using the Content Management API.

Draft - Unpublished
If an entry was published and has since been unpublished, it’ll have a sys.firstPublishedAt property.

An archived entry is not considered draft. If it has been archived, the entry will have 3 properties: sys.archivedAt, sys.archivedBy, and sys.archivedVersion

Hi @joakim.millen :wave:

What is so strange about this? What would you expect to happen?

I might of course be off, but in my opinion being able to know which items are drafts and which are published when using the preview API might be useful to for example highlight stuff in a preview page that has changed etc. It might also, as in my case, be of use when implementing a third party script that does different things to the content based on its status.

I can of course in that case just use the CMA since i have that available and implement it anyways but everyone might not.

And just as a side note, I would personally find it a lot more helpful with a sys.status or something that has some enum values like changed, published, archived, draft rather than the rather strange way to find out if a entry is published today.

entity.sys.version == entity.sys.publishedVersion + 1

this is so illogical to me.

1 Like

I totally agree with @joakim.millen. The preview API should tell you what state the document is in. The issue would solved easily by his simple, backwards-compatible fix. The fact that this improvement hasn’t been made in over two years can only be described in one word: lame. Needless to say I have moved on from using contentful. I’m still sad to see such a promising product isn’t improving in core areas.


1 Like

For anyone else looking to use this, updatedAt timestamp comparisons should be done only to a 10th of a second. Published entries can have a 100th of a second difference when comparing the Delivery API and Preview API responses.

Came searching for how to determine if an entry is draft or published and saddened to see it’s not possible.
Our specific situation is:
We use the Preview API for our Development environment and Delivery API for our Production environment. For some certain data we only want 1 single entry, and if there’s more than 1 returned we want to throw an alert.
Making double the API calls is not a reasonable answer.

1 Like

Is this still an issue? We can’t find a way to tell published content from draft content.

I’m assuming these docs are outdated: Determine the state of entries and assets | Contentful.

1 Like

Those docs are still correct. There is no direct indication in the Content Preview API (CPA) response for the status (i.e., draft, published, changed, archived) of an entry. This is because the CPA works exactly the same way as the Content Delivery API (CDA) except it has access to draft and changed entries as well as published entries.

In your preview app, if you need to know the status of some entries, you can do something like I outlined above which would then give each entry a sys.status property.

Hope this helps!

Exactly - Why on earth this isn’t detailed in the attributes is just beyond me?

We use a Webhook to indicate that some content is in draft or changed state, but the preview isn’t then capable of providing the same state for all the linked content of that item. I’m really disappointed to learn today (2022-11-29) that the only workaround is to still make multiple ‘expensive’ CMA calls to get this information.

Is there any other idea or work around to know the status of an entry with a single call using Preview API? This sounds to me as it should be a core feature

What’s strange is the glaring omission of what most seem to consider to be pertinent metadata about content. I’ve given my team access to a “preview” environment wherein I was trying to tag draft and once-published-but-then-unpublished posts accordingly. Is this really an unfathomable use case for the Contentful engineers? I’m half considering adding my own damned “Post Status” field to the content model and having my users use that instead, but then I’m forfeiting functionality like scheduled publishes, etc.

There’s no reason that both the CDA and CPA can’t both just tell me what status an entity is in — in plain english. Is there some security concern? Do I need to switch my preview environment to use the CMA token instead, just for this? And then I still have to implement that weird-ass workaround to calculate the status myself? Is this not a CMS platform? Am I — are we — taking crazy pills? WHAT IS HAPPENING?!