Control Panels

Control panels in Plone allow you to configure the global site setup of a Plone site. The @controlpanels endpoint in plone.restapi allows you to list all existing control panels in a Plone site and to retrieve or edit the settings of a specific control panel.

Most of the settings in the Plone control panels are based on plone.registry (since Plone 5.x). Therefore you can also use the @registry endpoint to retrieve or manipulate site settings. The @controlpanels endpoint just gives developers are more a convenience way of accessing the settings and makes it easier to render control panels on the front-end.

Note

This is currently only implemented for Plone 5.

Listing Control Panels

A list of all existing control panels in the portal can be retrieved by sending a GET request to the @controlpanels endpoint:

http

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

curl

curl -i http://nohost/plone/@controlpanels -H 'Accept: application/json' --user admin:secret

httpie

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

python-requests

requests.get('http://nohost/plone/@controlpanels', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))

Response:

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

[
    {
        "@id": "http://localhost:55001/plone/@controlpanels/date-and-time",
        "group": "General",
        "title": "Date and Time"
    },
    {
        "@id": "http://localhost:55001/plone/@controlpanels/language",
        "group": "General",
        "title": "Language"
    },
    {
        "@id": "http://localhost:55001/plone/@controlpanels/mail",
        "group": "General",
        "title": "Mail"
    },
    {
        "@id": "http://localhost:55001/plone/@controlpanels/navigation",
        "group": "General",
        "title": "Navigation"
    },
    {
        "@id": "http://localhost:55001/plone/@controlpanels/search",
        "group": "General",
        "title": "Search"
    },
    {
        "@id": "http://localhost:55001/plone/@controlpanels/site",
        "group": "General",
        "title": "Site"
    },
    {
        "@id": "http://localhost:55001/plone/@controlpanels/socialmedia",
        "group": "General",
        "title": "Social Media"
    },
    {
        "@id": "http://localhost:55001/plone/@controlpanels/dexterity-types",
        "group": "Content",
        "title": "Dexterity Content Types"
    },
    {
        "@id": "http://localhost:55001/plone/@controlpanels/editing",
        "group": "Content",
        "title": "Editing"
    },
    {
        "@id": "http://localhost:55001/plone/@controlpanels/imaging",
        "group": "Content",
        "title": "Image Handling"
    },
    {
        "@id": "http://localhost:55001/plone/@controlpanels/markup",
        "group": "Content",
        "title": "Markup"
    },
    {
        "@id": "http://localhost:55001/plone/@controlpanels/security",
        "group": "Security",
        "title": "Security"
    }
]

The following fields are returned:

  • @id: hypermedia link to the control panel
  • title: the title of the control panel
  • group: the group where the control panel should show up (e.g. General, Content, Users, Security, Advanced, Add-on Configuration)

Retrieve a single Control Panel

To retrieve a single control panel, send a GET request to the URL of the control panel:

http

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

curl

curl -i http://nohost/plone/@controlpanels/editing -H 'Accept: application/json' --user admin:secret

httpie

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

python-requests

requests.get('http://nohost/plone/@controlpanels/editing', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))

Response:

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

{
    "@id": "http://localhost:55001/plone/@controlpanels/editing",
    "data": {
        "available_editors": [
            "TinyMCE",
            "None"
        ],
        "default_editor": {
            "title": "TinyMCE",
            "token": "TinyMCE"
        },
        "enable_link_integrity_checks": true,
        "ext_editor": false,
        "lock_on_ttw_edit": true,
        "subjects_of_navigation_root": false
    },
    "group": "Content",
    "schema": {
        "fieldsets": [
            {
                "behavior": "plone",
                "fields": [
                    "available_editors",
                    "default_editor",
                    "ext_editor",
                    "enable_link_integrity_checks",
                    "lock_on_ttw_edit",
                    "subjects_of_navigation_root"
                ],
                "id": "default",
                "title": "Default"
            }
        ],
        "properties": {
            "available_editors": {
                "additionalItems": true,
                "default": [
                    "TinyMCE",
                    "None"
                ],
                "description": "Available editors in the portal.",
                "factory": "List",
                "items": {
                    "description": "",
                    "factory": "Text line (String)",
                    "title": "",
                    "type": "string"
                },
                "title": "Available editors",
                "type": "array",
                "uniqueItems": false
            },
            "default_editor": {
                "default": "TinyMCE",
                "description": "Select the default wysiwyg editor. Users will be able to choose their own or select to use the site default.",
                "factory": "Choice",
                "title": "Default editor",
                "type": "string",
                "vocabulary": {
                    "@id": "http://localhost:55001/plone/@vocabularies/plone.app.vocabularies.AvailableEditors"
                }
            },
            "enable_link_integrity_checks": {
                "default": true,
                "description": "Determines if the users should get warnings when they delete or move content that is linked from inside the site.",
                "factory": "Yes/No",
                "title": "Enable link integrity checks",
                "type": "boolean"
            },
            "ext_editor": {
                "default": false,
                "description": "Determines if the external editor feature is enabled. This feature requires a special client-side application installed. The users also have to enable this in their preferences.",
                "factory": "Yes/No",
                "title": "Enable External Editor feature",
                "type": "boolean"
            },
            "lock_on_ttw_edit": {
                "default": true,
                "description": "Disabling locking here will only affect users editing content through the Plone web UI.  Content edited via WebDAV clients will still be subject to locking.",
                "factory": "Yes/No",
                "title": "Enable locking for through-the-web edits",
                "type": "boolean"
            },
            "subjects_of_navigation_root": {
                "default": false,
                "description": "Limit tags aka keywords vocabulary used for Tags field and in searches to the terms used inside the subtree of the current navigation root. This can be used together with Plone's multilingual extension plone.app.multilingual to only offer keywords of the current selected language. Other addons may utilize this feature for its specific purposes.",
                "factory": "Yes/No",
                "title": "Limit tags/keywords to the current navigation root",
                "type": "boolean"
            }
        },
        "required": [
            "available_editors",
            "default_editor"
        ],
        "type": "object"
    },
    "title": "Editing"
}

The following fields are returned:

  • @id: hypermedia link to the control panel
  • title: title of the control panel
  • group: group name of the control panel
  • schema: JSON Schema of the control panel
  • data: current values of the control panel

Updating a Control Panel with PATCH

To update the settings on a control panel send a PATCH request to control panel resource:

http

PATCH /plone/@controlpanels/editing HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json

{
  "default_editor": "CKeditor",
  "ext_editor": true
}

curl

curl -i -X PATCH http://nohost/plone/@controlpanels/editing -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"default_editor": "CKeditor", "ext_editor": true}' --user admin:secret

httpie

echo '{
  "default_editor": "CKeditor",
  "ext_editor": true
}' | http PATCH http://nohost/plone/@controlpanels/editing Accept:application/json Content-Type:application/json -a admin:secret

python-requests

requests.patch('http://nohost/plone/@controlpanels/editing', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'default_editor': 'CKeditor', 'ext_editor': True}, auth=('admin', 'secret'))

A successful response to a PATCH request will be indicated by a 204 No Content response:

HTTP/1.1 204 No Content

Control Panels not based on plone.registry

Control panel which are not based on plone.registry have a custom @controlpanels/:panel endpoint implementation.

Dexterity Types

@controlpanels/dexterity-types is a custom control panel endpoint, that will allow you to add, remove and configure available Types

Reading or writing Dexterity Content Types require the plone.schemaeditor.ManageSchemata permission.

Verb URL Action
GET /@controlpanels/dexterity-types List configurable content-types
POST /@controlpanels/dexterity-types Creates a new content-type
GET /@controlpanels/dexterity-types/{type-id} Get the current state of the content-type
PATCH /@controlpanels/dexterity-types/{type-id} Update the content-type details
DELETE /@controlpanels/dexterity-types/{type-id} Remove content-type

Listing Dexterity Content Types

To list the available content-types send a GET request to @controlpanels/dexterity-types

http

GET /plone/@controlpanels/dexterity-types HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0

curl

curl -i http://nohost/plone/@controlpanels/dexterity-types -H 'Accept: application/json' --user admin:secret

httpie

http http://nohost/plone/@controlpanels/dexterity-types Accept:application/json -a admin:secret

python-requests

requests.get('http://nohost/plone/@controlpanels/dexterity-types', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))

Response:

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

{
    "@id": "http://localhost:55001/plone/@controlpanels/dexterity-types",
    "data": {},
    "group": "Content",
    "items": [
        {
            "@id": "http://localhost:55001/plone/@controlpanels/dexterity-types/Collection",
            "@type": "Collection",
            "count": 0,
            "description": "",
            "id": "Collection",
            "meta_type": "Dexterity FTI",
            "title": "Collection"
        },
        {
            "@id": "http://localhost:55001/plone/@controlpanels/dexterity-types/Document",
            "@type": "Document",
            "count": 0,
            "description": "",
            "id": "Document",
            "meta_type": "Dexterity FTI",
            "title": "Page"
        },
        {
            "@id": "http://localhost:55001/plone/@controlpanels/dexterity-types/Folder",
            "@type": "Folder",
            "count": 0,
            "description": "",
            "id": "Folder",
            "meta_type": "Dexterity FTI",
            "title": "Folder"
        },
        {
            "@id": "http://localhost:55001/plone/@controlpanels/dexterity-types/Link",
            "@type": "Link",
            "count": 0,
            "description": "",
            "id": "Link",
            "meta_type": "Dexterity FTI",
            "title": "Link"
        },
        {
            "@id": "http://localhost:55001/plone/@controlpanels/dexterity-types/File",
            "@type": "File",
            "count": 0,
            "description": "Lets you upload a file to the site.",
            "id": "File",
            "meta_type": "Dexterity FTI",
            "title": "File"
        },
        {
            "@id": "http://localhost:55001/plone/@controlpanels/dexterity-types/Image",
            "@type": "Image",
            "count": 0,
            "description": "Images can be referenced in pages or displayed in an album.",
            "id": "Image",
            "meta_type": "Dexterity FTI",
            "title": "Image"
        },
        {
            "@id": "http://localhost:55001/plone/@controlpanels/dexterity-types/News Item",
            "@type": "News Item",
            "count": 0,
            "description": "",
            "id": "News Item",
            "meta_type": "Dexterity FTI",
            "title": "News Item"
        },
        {
            "@id": "http://localhost:55001/plone/@controlpanels/dexterity-types/Event",
            "@type": "Event",
            "count": 0,
            "description": "Events can be shown in calendars.",
            "id": "Event",
            "meta_type": "Dexterity FTI",
            "title": "Event"
        },
        {
            "@id": "http://localhost:55001/plone/@controlpanels/dexterity-types/DXTestDocument",
            "@type": "DXTestDocument",
            "count": 0,
            "description": "",
            "id": "DXTestDocument",
            "meta_type": "Dexterity FTI",
            "title": "DX Test Document"
        }
    ],
    "schema": {
        "fieldsets": [],
        "properties": {},
        "required": [],
        "type": "object"
    },
    "title": "Dexterity Content Types"
}

The following fields are returned:

  • @id: hypermedia link to the control panel
  • title: title of the control panel
  • group: group name of the control panel
  • schema: JSON Schema of the control panel
  • data: current values of the control panel
  • items: list of configurable content-types.

Creating a new Dexterity Type with POST

To create a new content-type, send a POST request to the /@controlpanels/dexterity-types endpoint.

http

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

{
    "description": "A custom content-type",
    "title": "My Custom Content Type"
}

curl

curl -i -X POST http://nohost/plone/@controlpanels/dexterity-types -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"description": "A custom content-type", "title": "My Custom Content Type"}' --user admin:secret

httpie

echo '{
  "description": "A custom content-type",
  "title": "My Custom Content Type"
}' | http POST http://nohost/plone/@controlpanels/dexterity-types Accept:application/json Content-Type:application/json -a admin:secret

python-requests

requests.post('http://nohost/plone/@controlpanels/dexterity-types', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'description': 'A custom content-type', 'title': 'My Custom Content Type'}, auth=('admin', 'secret'))

Response:

HTTP/1.1 201 Created
Content-Type: application/json
Location: http://localhost:55001/plone/@controlpanels/dexterity-types/my_custom_content_type

{
    "@id": "http://localhost:55001/plone/@controlpanels/dexterity-types/my_custom_content_type",
    "data": {
        "allowed_content_types": [],
        "description": "A custom content-type",
        "filter_content_types": true,
        "plone.allowdiscussion": false,
        "plone.basic": false,
        "plone.categorization": false,
        "plone.collection": false,
        "plone.constraintypes": false,
        "plone.dublincore": true,
        "plone.eventattendees": false,
        "plone.eventbasic": false,
        "plone.eventcontact": false,
        "plone.eventlocation": false,
        "plone.eventrecurrence": false,
        "plone.excludefromnavigation": false,
        "plone.leadimage": false,
        "plone.locking": false,
        "plone.namefromfilename": false,
        "plone.namefromtitle": true,
        "plone.navigationroot": false,
        "plone.nextpreviousenabled": false,
        "plone.nextprevioustoggle": false,
        "plone.ownership": false,
        "plone.publication": false,
        "plone.relateditems": false,
        "plone.restapi.tests.dxtypes.ITestAnnotationsBehavior": false,
        "plone.restapi.tests.dxtypes.ITestBehavior": false,
        "plone.richtext": false,
        "plone.shortname": false,
        "plone.tableofcontents": false,
        "plone.thumb_icon": false,
        "plone.translatable": false,
        "plone.versioning": false,
        "title": "My Custom Content Type",
        "volto.blocks": false
    },
    "description": "A custom content-type",
    "group": "Content",
    "items": [],
    "schema": {
        "fieldsets": [
            {
                "behavior": "plone",
                "fields": [
                    "title",
                    "description",
                    "allowed_content_types",
                    "filter_content_types"
                ],
                "id": "default",
                "title": "Default"
            },
            {
                "behavior": "plone",
                "fields": [
                    "plone.allowdiscussion",
                    "plone.basic",
                    "volto.blocks",
                    "plone.categorization",
                    "plone.collection",
                    "plone.publication",
                    "plone.dublincore",
                    "plone.eventattendees",
                    "plone.eventbasic",
                    "plone.eventcontact",
                    "plone.eventlocation",
                    "plone.eventrecurrence",
                    "plone.excludefromnavigation",
                    "plone.constraintypes",
                    "plone.leadimage",
                    "plone.locking",
                    "plone.translatable",
                    "plone.namefromfilename",
                    "plone.namefromtitle",
                    "plone.navigationroot",
                    "plone.nextpreviousenabled",
                    "plone.nextprevioustoggle",
                    "plone.ownership",
                    "plone.relateditems",
                    "plone.richtext",
                    "plone.shortname",
                    "plone.tableofcontents",
                    "plone.restapi.tests.dxtypes.ITestAnnotationsBehavior",
                    "plone.restapi.tests.dxtypes.ITestBehavior",
                    "plone.thumb_icon",
                    "plone.versioning"
                ],
                "id": "behaviors",
                "title": "Behaviors"
            }
        ],
        "properties": {
            "allowed_content_types": {
                "additionalItems": true,
                "description": "",
                "factory": "Multiple Choice",
                "items": {
                    "description": "",
                    "factory": "Choice",
                    "title": "",
                    "type": "string",
                    "vocabulary": {
                        "@id": "http://localhost:55001/plone/@vocabularies/plone.app.vocabularies.ReallyUserFriendlyTypes"
                    }
                },
                "title": "Allowed Content Types",
                "type": "array",
                "uniqueItems": true
            },
            "description": {
                "description": "",
                "factory": "Text",
                "title": "Description",
                "type": "string",
                "widget": "textarea"
            },
            "filter_content_types": {
                "choices": [
                    [
                        "none",
                        null
                    ],
                    [
                        "all",
                        null
                    ],
                    [
                        "some",
                        null
                    ]
                ],
                "default": "none",
                "description": "Items of this type can act as a folder containing other  items. What content types should be allowed inside?",
                "enum": [
                    "none",
                    "all",
                    "some"
                ],
                "enumNames": [
                    null,
                    null,
                    null
                ],
                "factory": "Choice",
                "title": "Filter Contained Types",
                "type": "string",
                "vocabulary": {
                    "@id": "http://localhost:55001/plone/@sources/filter_content_types"
                }
            },
            "plone.allowdiscussion": {
                "description": "Allow discussion on this item",
                "factory": "Yes/No",
                "title": "Allow discussion",
                "type": "boolean"
            },
            "plone.basic": {
                "description": "Adds title and description fields.",
                "factory": "Yes/No",
                "title": "Basic metadata",
                "type": "boolean"
            },
            "plone.categorization": {
                "description": "Adds keywords and language fields.",
                "factory": "Yes/No",
                "title": "Categorization",
                "type": "boolean"
            },
            "plone.collection": {
                "description": "Adds collection behavior",
                "factory": "Yes/No",
                "title": "Collection",
                "type": "boolean"
            },
            "plone.constraintypes": {
                "description": "Restrict the content types that can be added to folderish content",
                "factory": "Yes/No",
                "title": "Folder Addable Constrains",
                "type": "boolean"
            },
            "plone.dublincore": {
                "description": "Adds standard metadata fields (equals Basic metadata + Categorization + Effective range + Ownership)",
                "factory": "Yes/No",
                "title": "Dublin Core metadata",
                "type": "boolean"
            },
            "plone.eventattendees": {
                "description": "Attendees extension for Events.",
                "factory": "Yes/No",
                "title": "Event Attendees",
                "type": "boolean"
            },
            "plone.eventbasic": {
                "description": "Basic Event schema.",
                "factory": "Yes/No",
                "title": "Event Basic",
                "type": "boolean"
            },
            "plone.eventcontact": {
                "description": "Contact extension for Events.",
                "factory": "Yes/No",
                "title": "Event Contact",
                "type": "boolean"
            },
            "plone.eventlocation": {
                "description": "Location extension for Events.",
                "factory": "Yes/No",
                "title": "Event Location",
                "type": "boolean"
            },
            "plone.eventrecurrence": {
                "description": "Recurrence extension for Events.",
                "factory": "Yes/No",
                "title": "Event Recurrence",
                "type": "boolean"
            },
            "plone.excludefromnavigation": {
                "description": "Allow items to be excluded from navigation",
                "factory": "Yes/No",
                "title": "Exclude From navigation",
                "type": "boolean"
            },
            "plone.leadimage": {
                "description": "Adds image and image caption fields",
                "factory": "Yes/No",
                "title": "Lead Image",
                "type": "boolean"
            },
            "plone.locking": {
                "description": "Locking support for dexterity",
                "factory": "Yes/No",
                "title": "Locking",
                "type": "boolean"
            },
            "plone.namefromfilename": {
                "description": "Automatically generate short URL name for content based on its primary field file name",
                "factory": "Yes/No",
                "title": "Name from file name",
                "type": "boolean"
            },
            "plone.namefromtitle": {
                "description": "Automatically generate short URL name for content based on its initial title",
                "factory": "Yes/No",
                "title": "Name from title",
                "type": "boolean"
            },
            "plone.navigationroot": {
                "description": "Make all items of this type a navigation root",
                "factory": "Yes/No",
                "title": "Navigation root",
                "type": "boolean"
            },
            "plone.nextpreviousenabled": {
                "description": "Enable next previous navigation for all items of this type",
                "factory": "Yes/No",
                "title": "Next previous navigation",
                "type": "boolean"
            },
            "plone.nextprevioustoggle": {
                "description": "Allow items to have next previous navigation enabled",
                "factory": "Yes/No",
                "title": "Next previous navigation toggle",
                "type": "boolean"
            },
            "plone.ownership": {
                "description": "Adds creator, contributor, and rights fields.",
                "factory": "Yes/No",
                "title": "Ownership",
                "type": "boolean"
            },
            "plone.publication": {
                "description": "Adds effective date and expiration date fields.",
                "factory": "Yes/No",
                "title": "Date range",
                "type": "boolean"
            },
            "plone.relateditems": {
                "description": "Adds the ability to assign related items",
                "factory": "Yes/No",
                "title": "Related items",
                "type": "boolean"
            },
            "plone.restapi.tests.dxtypes.ITestAnnotationsBehavior": {
                "description": "Schema-only behavior using annotations",
                "factory": "Yes/No",
                "title": "Test Annotations Behavior",
                "type": "boolean"
            },
            "plone.restapi.tests.dxtypes.ITestBehavior": {
                "description": "Schema-only behavior using attributes",
                "factory": "Yes/No",
                "title": "Test Behavior",
                "type": "boolean"
            },
            "plone.richtext": {
                "description": "Adds richtext behavior",
                "factory": "Yes/No",
                "title": "RichText",
                "type": "boolean"
            },
            "plone.shortname": {
                "description": "Gives the ability to rename an item from its edit form.",
                "factory": "Yes/No",
                "title": "Short name",
                "type": "boolean"
            },
            "plone.tableofcontents": {
                "description": "Adds a table of contents",
                "factory": "Yes/No",
                "title": "Table of contents",
                "type": "boolean"
            },
            "plone.thumb_icon": {
                "description": "Options to suppress thumbs and/or icons and to override thumb size in listings, tables etc.",
                "factory": "Yes/No",
                "title": "Thumbs and icon handling",
                "type": "boolean"
            },
            "plone.translatable": {
                "description": "Make this content type multilingual aware",
                "factory": "Yes/No",
                "title": "Multilingual Support",
                "type": "boolean"
            },
            "plone.versioning": {
                "description": "Versioning support with CMFEditions",
                "factory": "Yes/No",
                "title": "Versioning",
                "type": "boolean"
            },
            "title": {
                "description": "",
                "factory": "Text line (String)",
                "title": "Type Name",
                "type": "string"
            },
            "volto.blocks": {
                "description": "Enables Volto Blocks support",
                "factory": "Yes/No",
                "title": "Blocks",
                "type": "boolean"
            }
        },
        "required": [
            "title",
            "filter_content_types"
        ],
        "type": "object"
    },
    "title": "My Custom Content Type"
}

Reading a Dexterity Type with GET

After a successful POST, access the content-type by sending a GET request to the /@controlpanels/dexterity-types/{type-id}:

http

GET /plone/@controlpanels/dexterity-types/my_custom_content_type HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0

curl

curl -i http://nohost/plone/@controlpanels/dexterity-types/my_custom_content_type -H 'Accept: application/json' --user admin:secret

httpie

http http://nohost/plone/@controlpanels/dexterity-types/my_custom_content_type Accept:application/json -a admin:secret

python-requests

requests.get('http://nohost/plone/@controlpanels/dexterity-types/my_custom_content_type', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))

Response:

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

{
    "@id": "http://localhost:55001/plone/@controlpanels/dexterity-types/my_custom_content_type",
    "data": {
        "allowed_content_types": [],
        "description": "A custom content-type",
        "filter_content_types": true,
        "plone.allowdiscussion": false,
        "plone.basic": false,
        "plone.categorization": false,
        "plone.collection": false,
        "plone.constraintypes": false,
        "plone.dublincore": true,
        "plone.eventattendees": false,
        "plone.eventbasic": false,
        "plone.eventcontact": false,
        "plone.eventlocation": false,
        "plone.eventrecurrence": false,
        "plone.excludefromnavigation": false,
        "plone.leadimage": false,
        "plone.locking": false,
        "plone.namefromfilename": false,
        "plone.namefromtitle": true,
        "plone.navigationroot": false,
        "plone.nextpreviousenabled": false,
        "plone.nextprevioustoggle": false,
        "plone.ownership": false,
        "plone.publication": false,
        "plone.relateditems": false,
        "plone.restapi.tests.dxtypes.ITestAnnotationsBehavior": false,
        "plone.restapi.tests.dxtypes.ITestBehavior": false,
        "plone.richtext": false,
        "plone.shortname": false,
        "plone.tableofcontents": false,
        "plone.thumb_icon": false,
        "plone.translatable": false,
        "plone.versioning": false,
        "title": "My Custom Content Type",
        "volto.blocks": false
    },
    "description": "A custom content-type",
    "group": "Content",
    "items": [],
    "schema": {
        "fieldsets": [
            {
                "behavior": "plone",
                "fields": [
                    "title",
                    "description",
                    "allowed_content_types",
                    "filter_content_types"
                ],
                "id": "default",
                "title": "Default"
            },
            {
                "behavior": "plone",
                "fields": [
                    "plone.allowdiscussion",
                    "plone.basic",
                    "volto.blocks",
                    "plone.categorization",
                    "plone.collection",
                    "plone.publication",
                    "plone.dublincore",
                    "plone.eventattendees",
                    "plone.eventbasic",
                    "plone.eventcontact",
                    "plone.eventlocation",
                    "plone.eventrecurrence",
                    "plone.excludefromnavigation",
                    "plone.constraintypes",
                    "plone.leadimage",
                    "plone.locking",
                    "plone.translatable",
                    "plone.namefromfilename",
                    "plone.namefromtitle",
                    "plone.navigationroot",
                    "plone.nextpreviousenabled",
                    "plone.nextprevioustoggle",
                    "plone.ownership",
                    "plone.relateditems",
                    "plone.richtext",
                    "plone.shortname",
                    "plone.tableofcontents",
                    "plone.restapi.tests.dxtypes.ITestAnnotationsBehavior",
                    "plone.restapi.tests.dxtypes.ITestBehavior",
                    "plone.thumb_icon",
                    "plone.versioning"
                ],
                "id": "behaviors",
                "title": "Behaviors"
            }
        ],
        "properties": {
            "allowed_content_types": {
                "additionalItems": true,
                "description": "",
                "factory": "Multiple Choice",
                "items": {
                    "description": "",
                    "factory": "Choice",
                    "title": "",
                    "type": "string",
                    "vocabulary": {
                        "@id": "http://localhost:55001/plone/@vocabularies/plone.app.vocabularies.ReallyUserFriendlyTypes"
                    }
                },
                "title": "Allowed Content Types",
                "type": "array",
                "uniqueItems": true
            },
            "description": {
                "description": "",
                "factory": "Text",
                "title": "Description",
                "type": "string",
                "widget": "textarea"
            },
            "filter_content_types": {
                "choices": [
                    [
                        "none",
                        null
                    ],
                    [
                        "all",
                        null
                    ],
                    [
                        "some",
                        null
                    ]
                ],
                "default": "none",
                "description": "Items of this type can act as a folder containing other  items. What content types should be allowed inside?",
                "enum": [
                    "none",
                    "all",
                    "some"
                ],
                "enumNames": [
                    null,
                    null,
                    null
                ],
                "factory": "Choice",
                "title": "Filter Contained Types",
                "type": "string",
                "vocabulary": {
                    "@id": "http://localhost:55001/plone/@sources/filter_content_types"
                }
            },
            "plone.allowdiscussion": {
                "description": "Allow discussion on this item",
                "factory": "Yes/No",
                "title": "Allow discussion",
                "type": "boolean"
            },
            "plone.basic": {
                "description": "Adds title and description fields.",
                "factory": "Yes/No",
                "title": "Basic metadata",
                "type": "boolean"
            },
            "plone.categorization": {
                "description": "Adds keywords and language fields.",
                "factory": "Yes/No",
                "title": "Categorization",
                "type": "boolean"
            },
            "plone.collection": {
                "description": "Adds collection behavior",
                "factory": "Yes/No",
                "title": "Collection",
                "type": "boolean"
            },
            "plone.constraintypes": {
                "description": "Restrict the content types that can be added to folderish content",
                "factory": "Yes/No",
                "title": "Folder Addable Constrains",
                "type": "boolean"
            },
            "plone.dublincore": {
                "description": "Adds standard metadata fields (equals Basic metadata + Categorization + Effective range + Ownership)",
                "factory": "Yes/No",
                "title": "Dublin Core metadata",
                "type": "boolean"
            },
            "plone.eventattendees": {
                "description": "Attendees extension for Events.",
                "factory": "Yes/No",
                "title": "Event Attendees",
                "type": "boolean"
            },
            "plone.eventbasic": {
                "description": "Basic Event schema.",
                "factory": "Yes/No",
                "title": "Event Basic",
                "type": "boolean"
            },
            "plone.eventcontact": {
                "description": "Contact extension for Events.",
                "factory": "Yes/No",
                "title": "Event Contact",
                "type": "boolean"
            },
            "plone.eventlocation": {
                "description": "Location extension for Events.",
                "factory": "Yes/No",
                "title": "Event Location",
                "type": "boolean"
            },
            "plone.eventrecurrence": {
                "description": "Recurrence extension for Events.",
                "factory": "Yes/No",
                "title": "Event Recurrence",
                "type": "boolean"
            },
            "plone.excludefromnavigation": {
                "description": "Allow items to be excluded from navigation",
                "factory": "Yes/No",
                "title": "Exclude From navigation",
                "type": "boolean"
            },
            "plone.leadimage": {
                "description": "Adds image and image caption fields",
                "factory": "Yes/No",
                "title": "Lead Image",
                "type": "boolean"
            },
            "plone.locking": {
                "description": "Locking support for dexterity",
                "factory": "Yes/No",
                "title": "Locking",
                "type": "boolean"
            },
            "plone.namefromfilename": {
                "description": "Automatically generate short URL name for content based on its primary field file name",
                "factory": "Yes/No",
                "title": "Name from file name",
                "type": "boolean"
            },
            "plone.namefromtitle": {
                "description": "Automatically generate short URL name for content based on its initial title",
                "factory": "Yes/No",
                "title": "Name from title",
                "type": "boolean"
            },
            "plone.navigationroot": {
                "description": "Make all items of this type a navigation root",
                "factory": "Yes/No",
                "title": "Navigation root",
                "type": "boolean"
            },
            "plone.nextpreviousenabled": {
                "description": "Enable next previous navigation for all items of this type",
                "factory": "Yes/No",
                "title": "Next previous navigation",
                "type": "boolean"
            },
            "plone.nextprevioustoggle": {
                "description": "Allow items to have next previous navigation enabled",
                "factory": "Yes/No",
                "title": "Next previous navigation toggle",
                "type": "boolean"
            },
            "plone.ownership": {
                "description": "Adds creator, contributor, and rights fields.",
                "factory": "Yes/No",
                "title": "Ownership",
                "type": "boolean"
            },
            "plone.publication": {
                "description": "Adds effective date and expiration date fields.",
                "factory": "Yes/No",
                "title": "Date range",
                "type": "boolean"
            },
            "plone.relateditems": {
                "description": "Adds the ability to assign related items",
                "factory": "Yes/No",
                "title": "Related items",
                "type": "boolean"
            },
            "plone.restapi.tests.dxtypes.ITestAnnotationsBehavior": {
                "description": "Schema-only behavior using annotations",
                "factory": "Yes/No",
                "title": "Test Annotations Behavior",
                "type": "boolean"
            },
            "plone.restapi.tests.dxtypes.ITestBehavior": {
                "description": "Schema-only behavior using attributes",
                "factory": "Yes/No",
                "title": "Test Behavior",
                "type": "boolean"
            },
            "plone.richtext": {
                "description": "Adds richtext behavior",
                "factory": "Yes/No",
                "title": "RichText",
                "type": "boolean"
            },
            "plone.shortname": {
                "description": "Gives the ability to rename an item from its edit form.",
                "factory": "Yes/No",
                "title": "Short name",
                "type": "boolean"
            },
            "plone.tableofcontents": {
                "description": "Adds a table of contents",
                "factory": "Yes/No",
                "title": "Table of contents",
                "type": "boolean"
            },
            "plone.thumb_icon": {
                "description": "Options to suppress thumbs and/or icons and to override thumb size in listings, tables etc.",
                "factory": "Yes/No",
                "title": "Thumbs and icon handling",
                "type": "boolean"
            },
            "plone.translatable": {
                "description": "Make this content type multilingual aware",
                "factory": "Yes/No",
                "title": "Multilingual Support",
                "type": "boolean"
            },
            "plone.versioning": {
                "description": "Versioning support with CMFEditions",
                "factory": "Yes/No",
                "title": "Versioning",
                "type": "boolean"
            },
            "title": {
                "description": "",
                "factory": "Text line (String)",
                "title": "Type Name",
                "type": "string"
            },
            "volto.blocks": {
                "description": "Enables Volto Blocks support",
                "factory": "Yes/No",
                "title": "Blocks",
                "type": "boolean"
            }
        },
        "required": [
            "title",
            "filter_content_types"
        ],
        "type": "object"
    },
    "title": "My Custom Content Type"
}

Updating a Dexterity Type with PATCH

To update an existing content-type we send a PATCH request to the server. PATCH allows to provide just a subset of the resource (the values you actually want to change).

http

PATCH /plone/@controlpanels/dexterity-types/my_custom_content_type HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json

{
    "description": "A content-type",
    "plone.richtext": true,
    "plone.versioning": true,
    "title": "My Content Type"
}

curl

curl -i -X PATCH http://nohost/plone/@controlpanels/dexterity-types/my_custom_content_type -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"description": "A content-type", "plone.richtext": true, "plone.versioning": true, "title": "My Content Type"}' --user admin:secret

httpie

echo '{
  "description": "A content-type",
  "plone.richtext": true,
  "plone.versioning": true,
  "title": "My Content Type"
}' | http PATCH http://nohost/plone/@controlpanels/dexterity-types/my_custom_content_type Accept:application/json Content-Type:application/json -a admin:secret

python-requests

requests.patch('http://nohost/plone/@controlpanels/dexterity-types/my_custom_content_type', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'description': 'A content-type', 'plone.richtext': True, 'plone.versioning': True, 'title': 'My Content Type'}, auth=('admin', 'secret'))

Response:

HTTP/1.1 204 No Content

Removing a Dexterity Type with DELETE

Delete an existing content-type by sending a DELETE request to the URL of an existing content-type:

http

DELETE /plone/@controlpanels/dexterity-types/my_custom_content_type HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0

curl

curl -i -X DELETE http://nohost/plone/@controlpanels/dexterity-types/my_custom_content_type -H 'Accept: application/json' --user admin:secret

httpie

http DELETE http://nohost/plone/@controlpanels/dexterity-types/my_custom_content_type Accept:application/json -a admin:secret

python-requests

requests.delete('http://nohost/plone/@controlpanels/dexterity-types/my_custom_content_type', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))

Response:

HTTP/1.1 204 No Content