Modern enterprises need flexible content management solutions that can be integrated into any tech stack. dotCMS offers powerful REST APIs that enable developers to create, manage, and deliver content programmatically. In this blog post, we'll build a content management interface built to demonstrate three key dotCMS APIs in action, showing you how to create a robust content management workflow.
Understanding dotCMS REST APIs
Before diving into implementation, let's examine the core APIs we'll be working with:
1. Content Type API
Defines content structure and fields
Handles field validation rules
2. Workflow API
Controls content lifecycle
Manages publishing states
Handles content versioning
3. Content API
Retrieves content with advanced filtering
Supports pagination and sorting
Enables content search capabilities
Setting Up the Development Environment
While our focus is on the dotCMS APIs, we'll clone a React application tailored to demonstrate their usage. Here's how to set up the project:
# If you've already initialized a dotCMS examples repo directory, skip this step; otherwise, navigate to the desired directory and run the following commands:
git init
git remote add -f origin https://github.com/dotCMS/examples.git
git sparse-checkout init
# Clone this demo's subdirectory from the repo:
git sparse-checkout set rest-api-demo $(git sparse-checkout list) --no-cone
git pull origin main
# Finally, run the project:
cd rest-api-demo
npm i
npm run dev
To get the demo app working we need to include this environment variable:
VITE_DOTCMS_API_TOKEN={your-dotcms-api-token}
In order to get an API token please follow this link: https://www2.dotcms.com/docs/latest/rest-api-authentication#APIToken
The Application in Action
Our demo application provides an intuitive interface for interacting with dotCMS's REST APIs. Let's walk through its key features:
Content Type Management


The home screen presents two core functionalities powered by the Content Type API:
A creation form for new content types
A list of existing content types with their actions
Each content type includes a "Create Content" action that demonstrates API chaining
Content Creation Flow

The content creation interface showcases the Workflow API in action, with text and Block Editor fields demonstrating field type flexibility. The real-time content list updates after successful creation.
Content Management

The right panel displays created content, retrieving content immediately after publishing. This real-time list updates using the Content API.
This implementation demonstrates key dotCMS API capabilities:
Content type creation and management
Content publishing workflow
Real-time content retrieval and display
The interface provides enterprise developers with a practical example of integrating dotCMS APIs into modern web applications while maintaining a clean, user-friendly experience.
Source Code Access
The complete source code for this demo application is available in the dotCMS examples repository: https://github.com/dotCMS/examples/tree/main/rest-api-demo
The repository includes all components and configurations shown in this tutorial, making it easy to review, practice, or otherwise learn in a variety of ways:
Explore the API integration patterns
Test different content type configurations
Adapt the code for your own projects
Understand best practices for dotCMS API implementation
Deep Dive: Content Type API
The Content Type API is fundamental to content management in dotCMS. Let's explore its capabilities, starting with a typical call and payload.
Creating a Content Type
POST /api/v1/contenttype
{
"clazz": "com.dotcms.contenttype.model.type.ImmutableSimpleContentType",
"host": "SYSTEM_HOST",
"folder": "SYSTEM_FOLDER",
"name": "demo-apis-blog-post",
"fields": [
{
"clazz": "com.dotcms.contenttype.model.field.TextField",
"indexed": true,
"required": true,
"name": "title",
"variable": "title"
},
{
"clazz": "com.dotcms.contenttype.model.field.ImmutableStoryBlockField",
"name": "block",
"searchable": true
}
]
}
Key aspects of the Content Type API include their direct properties, their field types, and their field properties.
Field Types
dotCMS has many standard content field types. We’ll be working with just a few of them.
Field types are specified by their class, which by Java convention corresponds to a “clazz” property. The simplest way to fetch a list of possible class values is through the fieldTypes endpoint, which requires no parameter:
GET /api/v1/fieldTypes
So, for example, the text field is specified by “com.dotcms.contenttype.model.field.ImmutableTextField”; all other clazz values begin the same way, with “com…Immutable,” so we’ll give one full-length example, and then a few more that have been shortened for ease of reading:
com.dotcms.contenttype.model.field.ImmutableTextField: The Text field, for basic text content
com…ImmutableStoryBlockField: The Block Editor, for rich content editing
…DateField: For temporal data
…KeyValueField: For non-structured information of various sorts
…RelationshipField: For content relationships
Each field has its own field properties that indicate how it should be treated within the context of the system, such as:
required: Makes field mandatory, such that content cannot be saved if it is blank.
indexed: If true, this field will be included in the system index.
searchable: Allows searching of content within the field
listed: Shows field directly in content search result listing page
Finally, there are properties that apply to entire content types at once:
host: Associates with a specific site
workflow: Links to workflow schemes (see below for more on this)
Workflow API: Content Lifecycle Management
The Workflow API handles content state transitions through user-defined workflow actions. Here's an example call meant to publish content:
PUT /api/v1/workflow/actions/default/fire/PUBLISH
{
"contentlet": {
"contentType": "demo-apis-blog-post",
"title": "My First Post",
"block": {
"type": "doc",
"content": [{
"type": "paragraph",
"content": [{
"type": "text",
"text": "Article content goes here"
}]
}]
}
}
}
Workflow States and Actions
When using workflows, you’ll commonly be calling default actions. There are eight default actions available — such as NEW, EDIT, PUBLISH, UNPUBLISH, etc. — and each content type assigns workflow actions to these defaults separately. In this way, two content types may react to the same PUBLISH call with different underlying actions, to better suit their individual needs.
PUT /api/v1/workflow/actions/{workflowId}/fire/{actionId}
{
"contentlet": {
// content data
},
"comments": "Ready for review",
"assignTo": "editor@company.com"
}
Content API: Advanced Querying
The Content API supports sophisticated content retrieval:
GET /api/v1/contenttype?per_page=100&orderby=modDate DESC
GET /api/content/render/false/query/+contentType:blog-post +working:true
Above, we can see calls that respectively fetch content types and contentlets — or, individual units of content. (In programming terms: Content types relate to contentlets as classes to objects.)
The examples above show an example of the use of both query and path parameters. Queries themselves use the Lucene syntax.
Some parameters may include, though are not limited to:
per_page: Results per page
orderby: Sorting criteria — an indexed field or system variable, followed by ASC or DESC for ascending or descending
query: Lucene query syntax
depth: Related content depth
The following query, which is a little more complex, returns blog post contentlets of the “tech” category, published within a date range:
// Complex query example
GET /api/content/render/false/query/+contentType:blog-post +categories:tech +publishDate:[20240101 TO 20241231]
Implementing the Interface
Our demo application provides two main views:
Content Type Creation
const CreateContentType = () => {
const handleSubmit = async (e) => {
e.preventDefault();
const response = await fetch('/api/v1/contenttype', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': Bearer ${token}
},
body: JSON.stringify({
// Content type definition
})
});
// Handle response
};
// Component JSX
};
Content Management
const CreateContent = () => {
const handlePublish = async (content) => {
const response = await fetch('/api/v1/workflow/actions/default/fire/PUBLISH', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': Bearer ${token}
},
body: JSON.stringify({
contentlet: content
})
});
// Handle response
};
// Component JSX
};
Enterprise Implementation Considerations
1. Authentication and Security
For an alternate way to handle tokens, the following endpoint provides a simple interface.
// JWT token handling
const getAuthToken = async () => {
const response = await fetch('/api/v1/authentication/api-token', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
user: 'api-user',
password: 'secure-password',
expirationDays: '10'
})
});
return response.json();
};
2. Error Handling
const handleApiError = (error) => {
if (error.response) {
switch (error.response.status) {
case 401:
// Handle authentication error
break;
case 403:
// Handle permissions error
break;
case 404:
// Handle not found
break;
default:
// Handle other errors
}
}
};
3. Performance Optimization
Some ideas to get the most out of your hardware might include:
To prevent excessive API calls, you may want to try one of the following tactics:
Caching frequent calls according to your implementation — for example, here are some guidelines for Next.JS
Implement request debouncing to limit the speed with which they’re sent
Use pagination — built in to all REST API calls — for large content sets
4. Monitoring and Logging
When in doubt, never be afraid to log anything and everything.
const logApiRequest = (endpoint, method, data) => {
console.log(`API ${method} ${endpoint}`, {
timestamp: new Date(),
data,
user: getCurrentUser()
});
};
Conclusion
dotCMS's REST APIs provide a robust foundation for building custom content management solutions. The combination of the Content Type API, Workflow API, and Content API enables developers to create flexible, scalable content management systems that can be integrated into any enterprise architecture.
This implementation demonstrates how to:
Create structured content types
Manage content lifecycle
Implement secure content operations
Build user-friendly interfaces
For enterprise developers, the key advantages include:
Full programmatic control over content
Flexible integration capabilities
Scalable content operations
Secure content management
For complete API documentation and advanced features, visit the dotCMS API Documentation.