Website Workflow

The website_workflow is the primary publication workflow assigned to editorial content (content pages and the structural content of a Webcloud7 site). It governs which content is publicly visible and which is only visible to editors, and it records a review history for every state change.

Overview

The workflow has five states. Editors move content between them either through normal user transitions or — when an integration needs to force a state — through the @set-state REST endpoint. Only the Published state grants the Anonymous role view access; in every other state the content is restricted to authenticated editorial users.

The review_state value that appears in REST responses is the full workflow state id, e.g. website_workflow--STATUS--veroffentlicht.

States

State id

Title

Public?

Description

website_workflow--STATUS--entwurf

Entwurf (Draft)

No

Initial state. Content is being authored and is visible only to editors.

website_workflow--STATUS--eingereicht

Eingereicht (Submitted)

No

Content has been submitted for review.

website_workflow--STATUS--veroffentlicht

Veröffentlicht (Published)

Yes

Content is publicly visible to anonymous visitors.

website_workflow--STATUS--privat

Privat (Private)

No

Content is explicitly kept private.

website_workflow--STATUS--arbeitskopie

Arbeitskopie (Working Copy)

No

Reserved for staging working copies (see Staging (Working Copies)). Content in this state has no user transitions.

Entwurf is the initial state: newly created content starts here.

Transitions

Transitions are user-triggered. The table lists each transition, the state it starts from, and the state it leads to.

Transition id

Title

From

To

website_workflow--TRANSITION--einreichen-zum-veroffentlichen--entwurf_eingereicht

einreichen zum Veröffentlichen (submit for publication)

Entwurf

Eingereicht

website_workflow--TRANSITION--veroffentlichen--entwurf_veroffentlicht

veröffentlichen (publish)

Entwurf

Veröffentlicht

website_workflow--TRANSITION--privat-schalten--entwurf_privat

privat schalten (make private)

Entwurf

Privat

website_workflow--TRANSITION--veroffentlichen--eingereicht_veroffentlicht

veröffentlichen (publish)

Eingereicht

Veröffentlicht

website_workflow--TRANSITION--zuruckweisen-nach-entwurf--eingereicht_entwurf

zurückweisen nach Entwurf (reject to draft)

Eingereicht

Entwurf

website_workflow--TRANSITION--zuruckziehen-nach-entwurf--eingereicht_entwurf

zurückziehen nach Entwurf (retract to draft)

Eingereicht

Entwurf

website_workflow--TRANSITION--zuruckziehen-nach-entwurf--privat_entwurf

zurückziehen nach Entwurf (retract to draft)

Privat

Entwurf

website_workflow--TRANSITION--zuruckziehen-nach-entwurf--veroffentlicht_entwurf

zurückziehen nach Entwurf (retract to draft)

Veröffentlicht

Entwurf

The Arbeitskopie state intentionally has no exit transitions — working copies are applied or discarded through the staging actions rather than through workflow transitions.

Note

The manager_bypass flag is enabled on this workflow, so Managers may move content between states even where a transition guard would otherwise prevent it.

Inspecting the current state

The review_state of any content object is part of its standard serialization.

GET /Plone/my-page HTTP/1.1
Host: localhost:8080
Accept: application/json

The response includes the current workflow state id:

{
    "@id": "http://localhost:8080/Plone/my-page",
    "@type": "ContentPage",
    "title": "My Page",
    "review_state": "website_workflow--STATUS--entwurf"
}

Executing a transition

To follow the normal workflow path, fire a transition with the standard Plone @workflow endpoint, using the transition id from the table above.

POST /Plone/my-page/@workflow/website_workflow--TRANSITION--veroffentlichen--entwurf_veroffentlicht HTTP/1.1
Host: localhost:8080
Accept: application/json
Content-Type: application/json

{
    "comment": "Ready for the public site"
}

JavaScript:

async function publish(pageUrl, token) {
    const transition =
        'website_workflow--TRANSITION--veroffentlichen--entwurf_veroffentlicht';
    const response = await fetch(`${pageUrl}/@workflow/${transition}`, {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`
        },
        body: JSON.stringify({ comment: 'Ready for the public site' })
    });
    return response.json();
}

Setting a state directly

The @set-state endpoint sets a workflow state directly, bypassing the normal transition graph. This is useful for migrations or integrations that need to put content into a specific state regardless of which transitions are currently available. The target state id is appended to the endpoint path.

POST /Plone/my-page/@set-state/website_workflow--STATUS--veroffentlicht HTTP/1.1
Host: localhost:8080
Accept: application/json
Content-Type: application/json

{
    "comment": "Direct publication via API"
}

Response (the newly written review-history entry):

HTTP/1.1 200 OK
Content-Type: application/json

{
    "action": "set state",
    "actor": "system",
    "comment": "Direct publication via API",
    "review_state": "published",
    "time": "2023-09-16T10:30:00+00:00",
    "title": "Published"
}

Python:

import requests

state = 'website_workflow--STATUS--veroffentlicht'
response = requests.post(
    f'http://localhost:8080/Plone/my-page/@set-state/{state}',
    headers={'Accept': 'application/json'},
    json={'comment': 'Direct publication via API'},
    auth=('editor', 'secret'),
)
print(response.json()['review_state'])  # website_workflow--STATUS--veroffentlicht

An unknown state id results in a 400 response with a WorkflowException error.

Reading the review history

Every state change — whether via a transition, a direct @set-state call, or an applied working copy — appends an entry to the review history. Retrieve it with the standard @history endpoint.

GET /Plone/my-page/@history HTTP/1.1
Host: localhost:8080
Accept: application/json

Each entry carries the action, actor, comment, review_state, title, and time of the change, in the same shape as the @set-state response above.