Workflows#

The @workflows service describes the workflows that can be assigned to content types, and changes which workflow the site assigns by default. It is available at the site root, and requires the Plone Site Setup: Types permission, as well as permission to use the REST API.

Use the Content type management service to change the workflow assignment of a content type, and the Workflow service to change the state of an item.

Method

Path

Result

GET

/@workflows

Every workflow, and the default workflow.

GET

/@workflows/{id}

One workflow with its states and transitions.

POST

/@workflows

Change the default workflow assignment.

List workflows#

Send a GET request to /@workflows to list every workflow.

http

GET /plone/@workflows HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0

curl

curl -i -X GET http://nohost/plone/@workflows -H "Accept: application/json" --user admin:secret

httpie

http http://nohost/plone/@workflows Accept:application/json -a admin:secret

python-requests

requests.get('http://nohost/plone/@workflows', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json

{
    "@id": "http://localhost:55001/plone/@workflows",
    "default": "simple_publication_workflow",
    "items": [
        {
            "@id": "http://localhost:55001/plone/@workflows/comment_review_workflow",
            "description": "A simple review workflow for comments",
            "id": "comment_review_workflow",
            "initial_state": "pending",
            "states": [
                "pending",
                "published",
                "rejected",
                "spam"
            ],
            "title": "Comment Review Workflow"
        },
        {
            "@id": "http://localhost:55001/plone/@workflows/plone_workflow",
            "description": " - Users can create content that is immediately publicly accessible. - Content can be submitted for publication by the content's creator or a Manager, which is typically done to promote events or news to the front page. - Reviewers can publish or reject content, content owners can retract their submissions. - While the content is awaiting review it is readable by anybody. - If content is published, it can only be retracted by a Manager.",
            "id": "plone_workflow",
            "initial_state": "visible",
            "states": [
                "pending",
                "private",
                "published",
                "visible"
            ],
            "title": "Community Workflow"
        },
        {
            "@id": "http://localhost:55001/plone/@workflows/folder_workflow",
            "description": " - Used in conjunction with the Community workflow. - Has no pending state. - Allows owner to publish the folder without approval.",
            "id": "folder_workflow",
            "initial_state": "visible",
            "states": [
                "private",
                "published",
                "visible"
            ],
            "title": "Community Workflow for Folders"
        },
        {
            "@id": "http://localhost:55001/plone/@workflows/intranet_folder_workflow",
            "description": " - Normally used with the Intranet/Extranet workflow on folder types. - Only has two states: Private and Internal Draft.",
            "id": "intranet_folder_workflow",
            "initial_state": "internal",
            "states": [
                "internal",
                "private"
            ],
            "title": "Intranet Workflow for Folders"
        },
        {
            "@id": "http://localhost:55001/plone/@workflows/intranet_workflow",
            "description": " - An intranet workflow where content is only accessible if you are logged in. - Basic states are: Internal Draft, Pending Review, Internally Published and Private. - Also has an Externally Published state, so you can make selected content available to people outside the intranet.",
            "id": "intranet_workflow",
            "initial_state": "internal",
            "states": [
                "internal",
                "internally_published",
                "pending",
                "private",
                "external"
            ],
            "title": "Intranet/Extranet Workflow"
        },
        {
            "@id": "http://localhost:55001/plone/@workflows/simple_publication_workflow",
            "description": " - Simple workflow that is useful for basic web sites. - Things start out as private, and can either be submitted for review, or published directly. - The creator of a content item can edit the item even after it is published.",
            "id": "simple_publication_workflow",
            "initial_state": "private",
            "states": [
                "pending",
                "private",
                "published"
            ],
            "title": "Simple Publication Workflow"
        },
        {
            "@id": "http://localhost:55001/plone/@workflows/comment_one_state_workflow",
            "description": "- Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work.",
            "id": "comment_one_state_workflow",
            "initial_state": "published",
            "states": [
                "published"
            ],
            "title": "Single State Workflow"
        },
        {
            "@id": "http://localhost:55001/plone/@workflows/one_state_workflow",
            "description": "- Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work.",
            "id": "one_state_workflow",
            "initial_state": "published",
            "states": [
                "published"
            ],
            "title": "Single State Workflow"
        }
    ]
}

The response contains @id, default, and items. default is the ID of the default workflow, or null when there is none. The items are sorted by title, and each has these properties:

Property

Description

@id

URL of the workflow in this service.

id

Workflow ID.

title

Translated title.

description

Translated description.

initial_state

ID of the state of new items.

states

IDs of the states, in the order of the workflow.

Get a workflow#

Send a GET request to /@workflows/{id} to get one workflow with its states and transitions. Unknown workflows return 404 Not Found.

http

GET /plone/@workflows/simple_publication_workflow HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0

curl

curl -i -X GET http://nohost/plone/@workflows/simple_publication_workflow -H "Accept: application/json" --user admin:secret

httpie

http http://nohost/plone/@workflows/simple_publication_workflow Accept:application/json -a admin:secret

python-requests

requests.get('http://nohost/plone/@workflows/simple_publication_workflow', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json

{
    "@id": "http://localhost:55001/plone/@workflows/simple_publication_workflow",
    "description": " - Simple workflow that is useful for basic web sites. - Things start out as private, and can either be submitted for review, or published directly. - The creator of a content item can edit the item even after it is published.",
    "id": "simple_publication_workflow",
    "initial_state": "private",
    "states": [
        {
            "description": "Waiting to be reviewed, not editable by the owner.",
            "id": "pending",
            "permission_roles": {
                "Access contents information": [
                    "Manager",
                    "Owner",
                    "Editor",
                    "Reader",
                    "Contributor",
                    "Reviewer",
                    "Site Administrator"
                ],
                "Modify portal content": [
                    "Manager",
                    "Reviewer",
                    "Site Administrator"
                ],
                "View": [
                    "Manager",
                    "Owner",
                    "Editor",
                    "Reader",
                    "Contributor",
                    "Reviewer",
                    "Site Administrator"
                ]
            },
            "title": "Pending review",
            "transitions": [
                "publish",
                "reject",
                "retract"
            ],
            "visibility": "restricted"
        },
        {
            "description": "Can only be seen and edited by the owner.",
            "id": "private",
            "permission_roles": {
                "Access contents information": [
                    "Manager",
                    "Owner",
                    "Editor",
                    "Reader",
                    "Contributor",
                    "Site Administrator"
                ],
                "Modify portal content": [
                    "Manager",
                    "Owner",
                    "Editor",
                    "Site Administrator"
                ],
                "View": [
                    "Manager",
                    "Owner",
                    "Editor",
                    "Reader",
                    "Contributor",
                    "Site Administrator"
                ]
            },
            "title": "Private",
            "transitions": [
                "publish",
                "submit"
            ],
            "visibility": "restricted"
        },
        {
            "description": "Visible to everyone, editable by the owner.",
            "id": "published",
            "permission_roles": {
                "Access contents information": [
                    "Anonymous"
                ],
                "Modify portal content": [
                    "Manager",
                    "Owner",
                    "Editor",
                    "Site Administrator"
                ],
                "View": [
                    "Anonymous"
                ]
            },
            "title": "Published with accent \u00e9",
            "transitions": [
                "retract",
                "reject"
            ],
            "visibility": "anyone"
        }
    ],
    "title": "Simple Publication Workflow",
    "transitions": [
        {
            "description": "Publishing the item makes it visible to other users.",
            "guard": {
                "expression": "",
                "permissions": [
                    "Review portal content"
                ],
                "roles": []
            },
            "id": "publish",
            "new_state": "published",
            "title": "Publish"
        },
        {
            "description": "Sending the item back will return the item to the original author instead of publishing it. You should preferably include a reason for why it was not published.",
            "guard": {
                "expression": "",
                "permissions": [
                    "Review portal content"
                ],
                "roles": []
            },
            "id": "reject",
            "new_state": "private",
            "title": "Send back"
        },
        {
            "description": "If you submitted the item by mistake or want to perform additional edits, this will take it back.",
            "guard": {
                "expression": "",
                "permissions": [
                    "Request review"
                ],
                "roles": []
            },
            "id": "retract",
            "new_state": "private",
            "title": "Retract"
        },
        {
            "description": "Puts your item in a review queue, so it can be published on the site.",
            "guard": {
                "expression": "",
                "permissions": [
                    "Request review"
                ],
                "roles": []
            },
            "id": "submit",
            "new_state": "pending",
            "title": "Submit for publication"
        }
    ],
    "types": [
        "ATTestDocument",
        "ATTestFolder",
        "Collection",
        "DXTestDocument",
        "Document",
        "Event",
        "Folder",
        "Link",
        "News Item",
        "TempFolder"
    ]
}

The response has the properties of the listing, and these:

Property

Description

states

The states, each with an id, a translated title and description, the IDs of the transitions leaving it, its visibility, and its permission_roles.

transitions

The transitions, each with an id, a translated title and description, the ID of its new_state, and its guard, with permissions, roles, and an expression.

types

IDs of the content types using the workflow, including those following the default workflow.

permission_roles maps each permission the state manages to the roles that have it. visibility summarizes who can see items in the state, from the roles with the View permission:

Value

Who can see items

anyone

Anonymous visitors.

members

Authenticated users. The roles include Authenticated or Member.

restricted

Only the roles listed, such as Owner, Reviewer, or Manager.

unknown

The state doesn't manage View, or it acquires the permission, so it depends on the container.

Change the default workflow assignment#

Send a POST request to /@workflows to assign another default workflow. It affects every content type that follows the default. The body has these properties:

Property

Description

default

ID of the new default workflow, or null for no default workflow. Required.

state_map

Maps the states of the current default workflow to states of the new one. Optional.

dry_run

When true, changes nothing, and returns the planned change.

Unknown workflows and unknown target states return 400 Bad Request.

Plan the change#

With dry_run, the service returns the number of items in each state, and a suggested new state for each.

http

POST /plone/@workflows HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json

{
    "default": "intranet_workflow",
    "dry_run": true
}

curl

curl -i -X POST http://nohost/plone/@workflows -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"default": "intranet_workflow", "dry_run": true}' --user admin:secret

httpie

echo '{
  "default": "intranet_workflow",
  "dry_run": true
}' | http POST http://nohost/plone/@workflows Accept:application/json Content-Type:application/json -a admin:secret

python-requests

requests.post('http://nohost/plone/@workflows', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'default': 'intranet_workflow', 'dry_run': True}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json

{
    "current": "simple_publication_workflow",
    "states": [
        {
            "count": 0,
            "id": "pending",
            "suggested": "private"
        },
        {
            "count": 1,
            "id": "private",
            "suggested": "private"
        },
        {
            "count": 1,
            "id": "published",
            "suggested": "external"
        }
    ],
    "types": [
        "ATTestDocument",
        "ATTestFolder",
        "Collection",
        "DXTestDocument",
        "Document",
        "Event",
        "Folder",
        "Link",
        "News Item",
        "TempFolder"
    ],
    "unaffected": 0,
    "workflow": "intranet_workflow"
}

Property

Description

workflow

ID of the new workflow, or null.

current

ID of the current workflow, or null.

states

One entry per state of the current workflow, in its order, with the state id, the count of items in it, and the suggested new state.

unaffected

Number of items that a placeful workflow policy gives another workflow, which the change doesn't affect.

types

IDs of the content types following the default workflow.

Without a current workflow, states has a single entry with an empty id, counting every item of the types. The counts include items the current user cannot view. suggested is null when the new workflow is null.

The suggested state keeps who can see the items. It's the most visible state of the new workflow that isn't more visible than the current state, comparing their visibility (unknown and restricted are the least visible, then members, then anyone). If every state is more visible, it's the least visible one. Among equally visible states, the service prefers the one with the same ID, then the one with the same title, then the initial state, then the first state.

Apply the change#

Without dry_run, the service changes the default workflow, moves the items of the types following it to their new states, and updates their security. States left out of state_map get the suggested state. The change happens during the request, as in the classic control panel, so it can take long on large sites.

http

POST /plone/@workflows HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json

{
    "default": "intranet_workflow",
    "state_map": {
        "private": "internal"
    }
}

curl

curl -i -X POST http://nohost/plone/@workflows -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"default": "intranet_workflow", "state_map": {"private": "internal"}}' --user admin:secret

httpie

echo '{
  "default": "intranet_workflow",
  "state_map": {
    "private": "internal"
  }
}' | http POST http://nohost/plone/@workflows Accept:application/json Content-Type:application/json -a admin:secret

python-requests

requests.post('http://nohost/plone/@workflows', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'default': 'intranet_workflow', 'state_map': {'private': 'internal'}}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json

{
    "changed": 2,
    "default": "intranet_workflow"
}

The response contains the new default and the number of changed items.