agentsclimarketplace

Api headless

Skill ColdBox/skills/contentbox-boxlang/api-headless

Collection of skills for the ColdBox Platform and Claude Plugin

Install
npx -y skills add ColdBox/skills --skill api-headless

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

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.

SKILL.md

9.1 KB, as published. Nobody here has run it

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

HandlerResourceDescription
auth.bxAuthenticationJWT token generation and validation
authors.bxAuthorsAuthor CRUD operations
categories.bxCategoriesCategory CRUD operations
comments.bxCommentsComment management
contentStore.bxContentStoreKey-value content blocks
contentTemplates.bxTemplatesContent template management
entries.bxEntriesBlog entry CRUD operations
menus.bxMenusMenu management
pages.bxPagesPage CRUD operations
relocations.bxRelocationsURL redirect management
settings.bxSettingsGlobal settings API
siteSettings.bxSite SettingsSite-specific settings
sites.bxSitesMulti-site management
versions.bxVersionsContent versioning
echo.bxHealth CheckAPI 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

ParameterDescription
pagePage number (default: 1)
maxRowsResults per page
sortOrderSort field and direction
isDeletedInclude soft-deleted entries
includesRelated entities to include
excludesFields 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, modifiedDate
  • author (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

  1. Extend baseHandler — get CRUD operations for free
  2. Inject ormService — use the correct virtual entity service
  3. Use variables.entity — set the singular entity name
  4. Set variables.sortOrder — define default sorting
  5. Use param for defaults — set safe defaults for query parameters
  6. Override methods as needed — customize index, show, etc.
  7. Use renderData() — for consistent JSON responses
  8. Announce interception points — for extensibility
  9. Include related entities — use includes parameter for nested data
  10. 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 .bx templates
  • Modern syntax: ?: null coalescing, ?. safe navigation
  • Native support for modern data structures

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.