contentbox-boxlang-api-headless
Use this skill when implementing headless ContentBox APIs, including REST endpoint design, JWT authentication flows, content CRUD, custom API handlers, and integration patterns for decoupled frontends.
ContentBox API & Headless Development (BoxLang)
Build headless and REST API integrations with ContentBox CMS using BoxLang. ContentBox provides a full REST API (v1) for managing all content types, enabling headless CMS architectures.
API Architecture
The API module lives at modules/contentbox/modules/contentbox-api/ with a nested v1 module at modules/contentbox/modules/contentbox-api/modules/contentbox-api-v1/.
API v1 Handlers
| Handler | Resource | Description |
|---|---|---|
auth.bx | Authentication | JWT token generation and validation |
authors.bx | Authors | Author CRUD operations |
categories.bx | Categories | Category CRUD operations |
comments.bx | Comments | Comment management |
contentStore.bx | ContentStore | Key-value content blocks |
contentTemplates.bx | Templates | Content template management |
entries.bx | Entries | Blog entry CRUD operations |
menus.bx | Menus | Menu management |
pages.bx | Pages | Page CRUD operations |
relocations.bx | Relocations | URL redirect management |
settings.bx | Settings | Global settings API |
siteSettings.bx | Site Settings | Site-specific settings |
sites.bx | Sites | Multi-site management |
versions.bx | Versions | Content versioning |
echo.bx | Health Check | API health check / echo |
Base Handler Pattern
API handlers extend BaseHandler (which extends cborm.models.resources.BaseHandler):
// handlers/api/v1/MyResource.bx
component extends="contentbox.modules.contentbox-api.modules.contentbox-api-v1.handlers.baseHandler" singleton {
// Inject the virtual entity service
property name="ormService" inject="MyEntityService@contentbox"
// Entity name (singular)
variables.entity = "MyEntity"
// Default sort order
variables.sortOrder = "createdDate DESC"
// Use native getOrFail() or getByIdOrSlugOrFail()
variables.useGetOrFail = true
}
This automatically provides: index, create, show, update, delete methods.
Authentication
JWT Authentication
The API uses JWT tokens for authentication:
POST /api/v1/auth
Body: { "username": "admin", "password": "secret" }
Response: { "token": "eyJhbGciOiJIUzI1NiIs...", "expires": 3600 }
Using Tokens
Include the token in the Authorization header:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
API Endpoints
Entries
GET /api/v1/entries โ List entries (paginated)
GET /api/v1/entries/:id โ Get single entry
POST /api/v1/entries โ Create entry
PUT /api/v1/entries/:id โ Update entry
DELETE /api/v1/entries/:id โ Delete entry
Query Parameters
| Parameter | Description |
|---|---|
page | Page number (default: 1) |
maxRows | Results per page |
sortOrder | Sort field and direction |
isDeleted | Include soft-deleted entries |
includes | Related entities to include |
excludes | Fields to exclude from response |
Pages
GET /api/v1/pages โ List pages
GET /api/v1/pages/:id โ Get single page (by ID or slug)
POST /api/v1/pages โ Create page
PUT /api/v1/pages/:id โ Update page
DELETE /api/v1/pages/:id โ Delete page
Categories
GET /api/v1/categories โ List categories
GET /api/v1/categories/:id โ Get single category
POST /api/v1/categories โ Create category
PUT /api/v1/categories/:id โ Update category
DELETE /api/v1/categories/:id โ Delete category
Authors
GET /api/v1/authors โ List authors
GET /api/v1/authors/:id โ Get single author
POST /api/v1/authors โ Create author
PUT /api/v1/authors/:id โ Update author
DELETE /api/v1/authors/:id โ Delete author
ContentStore
GET /api/v1/contentstore โ List all content store items
GET /api/v1/contentstore/:key โ Get item by key
POST /api/v1/contentstore โ Create item
PUT /api/v1/contentstore/:key โ Update item
DELETE /api/v1/contentstore/:key โ Delete item
Menus
GET /api/v1/menus โ List menus
GET /api/v1/menus/:slug โ Get menu by slug
POST /api/v1/menus โ Create menu
PUT /api/v1/menus/:slug โ Update menu
DELETE /api/v1/menus/:slug โ Delete menu
Sites
GET /api/v1/sites โ List sites
GET /api/v1/sites/:id โ Get single site
POST /api/v1/sites โ Create site
PUT /api/v1/sites/:id โ Update site
DELETE /api/v1/sites/:id โ Delete site
Response Format
List Response
{
"data": [
{ "id": "...", "title": "...", "slug": "...", ... }
],
"total": 100,
"page": 1,
"maxRows": 25
}
Single Resource Response
{
"data": {
"id": "...",
"title": "...",
"slug": "...",
"content": "...",
"author": { ... },
"categories": [ ... ],
...
}
}
Error Response
{
"error": true,
"message": "Resource not found",
"details": "..."
}
Creating Custom API Endpoints
Custom API Handler
// handlers/api/v1/CustomResource.bx
component extends="contentbox.modules.contentbox-api.modules.contentbox-api-v1.handlers.baseHandler" singleton {
property name="ormService" inject="CustomEntityService@contentbox"
variables.entity = "CustomEntity"
variables.sortOrder = "createdDate DESC"
// Override index for custom filtering
function index( event, rc, prc, criteria, results ){
// Custom filtering logic
prc.criteria = ormService.newCriteria()
if( structKeyExists( rc, "status" ) ){
prc.criteria.isEq( "status", rc.status )
}
// Delegate to parent
super.index( event, rc, prc, prc.criteria )
}
// Add custom action
function publish( event, rc, prc ){
entity = ormService.get( rc.id )
entity.setStatus( "published" )
ormService.save( entity )
renderData(
type : "json",
data : { success : true, entity : entity.getMemento() },
statusCode : 200
)
}
}
Custom API Routes
Register routes in your module's ModuleConfig.bx:
routes = [
// RESTful resources
{ pattern : "/api/v1/custom", handler : "api/v1/customResource" },
{ pattern : "/api/v1/custom/:id", handler : "api/v1/customResource" },
// Custom actions
{ pattern : "/api/v1/custom/:id/publish", handler : "api/v1/customResource", action : "publish" }
]
Headless CMS Usage
Frontend Integration
Use the API to build headless frontends:
// Fetch entries
const response = await fetch('/api/v1/entries?page=1&maxRows=10', {
headers: { 'Authorization': `Bearer ${token}` }
});
const { data, total, page } = await response.json();
// Fetch single page by slug
const pageResponse = await fetch('/api/v1/pages/my-page-slug', {
headers: { 'Authorization': `Bearer ${token}` }
});
const { data: page } = await pageResponse.json();
Content Rendering
The API returns content with all fields, including:
title,slug,content(HTML)publishedDate,createdDate,modifiedDateauthor(nested object)categories(array)customFields(if configured)featuredImage(media reference)
API Security
Firewall Rules
API routes are protected by cbSecurity rules. Configure in settings:
settings.cbsecurity = {
firewall : {
invalidAuthenticationEvent : "cbapi/auth/unauthorized",
defaultAuthenticationAction : "redirect",
invalidAuthorizationEvent : "cbapi/auth/forbidden",
defaultAuthorizationAction : "redirect"
}
}
Rate Limiting
The core RateLimiter@contentbox interceptor protects against brute-force attacks.
Best Practices
- Extend
baseHandlerโ get CRUD operations for free - Inject
ormServiceโ use the correct virtual entity service - Use
variables.entityโ set the singular entity name - Set
variables.sortOrderโ define default sorting - Use
paramfor defaults โ set safe defaults for query parameters - Override methods as needed โ customize
index,show, etc. - Use
renderData()โ for consistent JSON responses - Announce interception points โ for extensibility
- Include related entities โ use
includesparameter for nested data - Handle errors gracefully โ return proper error responses
Engine Compatibility
This skill targets BoxLang engine. For CFML-specific syntax (Lucee 5+, Adobe ColdFusion 2018+), see the CFML variant of this skill.
Key BoxLang advantages:
- Cleaner script syntax without
<cfcomponent>/<cffunction>tags - No parentheses needed for zero-argument function calls
#{...}#for inline expression output in.bxtemplates- Modern syntax:
?:null coalescing,?.safe navigation - Native support for modern data structures