Query Regarding Unpublishing Headless Content After End Date via Scheduler

2025/11/20 10:17 AM

I am currently working with Headless content types in Xperience by Kentico, and I have a requirement where I need to automatically unpublish content items once their configured End Date has passed.

To achieve this, I am planning to create a scheduled task that checks all relevant headless content items, compares their End Date with the current date, and unpublishes the content if it is already past the End Date.

Could you please confirm:

  1. Is this approach recommended for headless content types?
  2. Is there any built-in API or best practice for programmatically unpublishing headless content items?
  3. Is there any sample implementation or documentation that can help with this scenario?

Environment

  • Xperience by Kentico version: [30.9.1]

  • .NET version: [8]

Tags:
Content management Content modeling Content types Headless channels

Answers

2025/11/20 1:19 PM
Accepted answer

This question caught my eye and I researched it. Headless content items don't provide scheduling unpublish like reusable content items, so using a scheduled task with a custom EndDate field feels like a reasonable approach.

I tried using contentItemManager.TryUnpublish() for headless items and found this limitation:

Error unpublishing content item 82 in language en: Provided content item with id '82' is not defined as reusable. Implementation is limited to work only with reusable content items.

After researching the Kentico API Reference and documentation, I found no documented programmatic API for unpublishing headless items. Unlike pages and reusable content items, there doesn't appear to be a corresponding API for headless items.

I think you might need to rethink the solution. Perhaps the unpublishing logic should be based on linked reusable content, where you can rely on the native support provided by the XbyK APIs. Or you can keep the EndDate field on the headless item, and the app consuming the GraphQL API will simply treat the item as unpublished once that date has passed. This really depends on you project structure and requirements. And of course, you can also submit an idea on the roadmap.

2025/11/21 6:34 AM

Hi Milan,

Thank you for the detailed explanation — you are absolutely correct. For now, we’ve implemented the logic on the frontend to ignore any headless items whose EndDate has already passed, so the content behaves as “unpublished” from the application’s perspective.

However, we are also looking for a solution where these headless items can be truly unpublished on the admin side as well, similar to how reusable content items support programmatic unpublishing. This would help us maintain consistency across both admin and frontend, especially for content governance.

If there’s any workaround or upcoming support planned for programmatically unpublishing headless items, that would be very helpful. Otherwise, we will consider submitting this as an idea on the roadmap.

Thanks again for your guidance!

2025/11/21 6:48 AM

Please submit the idea as soon as possible. If the Kentico product management team doesn’t see demand for this feature, they won’t invest in it.

2025/11/21 8:01 PM

I really like Milan's suggestion:

the unpublishing logic should be based on linked reusable content, where you can rely on the native support provided by the XbyK APIs.

I actually came to the same solution independently!

The EndDate option is also a good one if you can depend on the client experience to respect it.

I also agree that submitting your idea and describing your scenario on the roadmap feedback is helpful.

2025/11/26 6:33 AM

Hi Milan & Sean,

I’ve now found a solution where I’m able to successfully unpublish headless items based on the EndDate using the IHeadlessItemManager, and everything is working as expected.

The only issue I’m facing is that, when creating the manager instance, we currently use:

this.headlessItemManager = headlessItemManagerFactory.Create(2, user.UserID);

Here, the headless channel ID is hard-coded, and I need to retrieve this value dynamically based on the context.

Right now I'm fetching the channelID via objectQuery, if any other option, so let me know.

2025/12/05 11:57 AM

I just returned to this because I’m dealing with a very similar issue right now. I need to migrate autoresponder emails in an Email channel, and I’ve just discovered that there’s no documented API for managing Email content items either.

The API you found for headless items is an internal one in the CMS.Headless.Internal namespace, so it’s not recommended to use it. Similarly, it looks like there’s an internal API for emails in the CMS.EmailLibrary.Internal namespace. Unfortunately, it’s pretty difficult to work with.

I’m wondering if Kentico plans to make these APIs public at some point. Since the migration tool doesn’t support migrating emails, it would make a lot of sense. We have dozens of autoresponder emails, and we’d really like to write a migration script for them.

2025/12/05 8:01 PM

Here, the headless channel ID is hard-coded, and I need to retrieve this value dynamically based on the context.

What is the context you are referring to?

Headless channels get this context based on the GraphQL query sent to the channel's API endpoint. If you are doing some background processing in the administration UI there is no current channel. You can use an Object Query to get a channel ID or name, but you need to decide which headless channel is the right one based on the "context".

I’m wondering if Kentico plans to make these APIs public at some point.

Those APIs (for headless and email content item management) are in .Internal namespaces to make them easier for us to use in the product and still have the flexibility to change them as needed for new features. We call these .Internal namespace but public class modifier types "pubternal". They're designed for the platform, not for consumption.

It requires a lot of planning and review when we make an API truly public and supported because it limits how we can evolve it in the future.

The API you found for headless items is an internal one in the CMS.Headless.Internal namespace, so it’s not recommended to use it.

Milan is right, we don't recommend using these APIs primarily because we might change them in a minor version update, without notice. Using them could put you in a situation where you can't apply a Refresh without losing functionality.

However, it might be worth it if you want the capabilities they enable! I use them in the Kentico Community Portal, and acknowledge the risk. I don't get special treatment just because I work for Kentico 😅.

If you have scenarios you need solved that these APIs support, give us feedback about them on our roadmap.

To response this discussion, you have to login first.