Skip to content

API Reference

The ACMS dev server exposes a REST API on port 4185 (by default) for managing content fields programmatically. This API is used by the client library, the dashboard, and can be used by custom tools.

http://localhost:4185/api

Retrieve the complete schema including fields, groups, and metadata.

GET /api/schema

Response:

{
"fields": {
"hero": {
"title": "Welcome to ACMS",
"subtitle": "Schema-less content management"
},
"contact": {
"email": "hello@example.com"
}
},
"groups": ["hero", "contact"],
"meta": {
"hero.title": {
"type": "string",
"lastAccessed": "2025-01-15T10:30:00.000Z"
},
"hero.subtitle": {
"type": "string",
"lastAccessed": "2025-01-15T10:30:00.000Z"
},
"contact.email": {
"type": "string",
"lastAccessed": "2025-01-15T10:30:00.000Z"
}
}
}

Retrieve content values without metadata. This is what the client library uses to fetch content.

GET /api/content

Response:

{
"hero": {
"title": "Welcome to ACMS",
"subtitle": "Schema-less content management"
},
"contact": {
"email": "hello@example.com"
}
}

Set or update a field’s value.

POST /api/field

Request body:

{
"path": "hero.title",
"value": "Welcome to My Site"
}

Response:

{
"success": true
}

Register a new field (used by the client proxy during development).

POST /api/register

Request body:

{
"path": "hero.title"
}

Response:

{
"success": true
}

If the field already exists, the endpoint returns success without modifying the value.

Update metadata for a field (type, label, default value, etc.).

PATCH /api/field/:path/meta

Example:

Terminal window
curl -X PATCH http://localhost:4185/api/field/hero.title/meta \
-H "Content-Type: application/json" \
-d '{"type": "text"}'

Request body:

{
"type": "text",
"label": "Hero Title",
"defaultValue": "Default Title"
}

Response:

{
"success": true
}

Remove a field from the schema.

DELETE /api/field/:path

Example:

Terminal window
curl -X DELETE http://localhost:4185/api/field/hero.subtitle

Response:

{
"success": true
}

Create a new field with a specified type.

POST /api/field/new

Request body:

{
"path": "hero.ctaText",
"type": "string",
"value": "Learn More"
}

Response:

{
"success": true
}

Add an item to an array field.

POST /api/array/:path/push

Example:

Terminal window
curl -X POST http://localhost:4185/api/array/features/push \
-H "Content-Type: application/json" \
-d '{"value": "New Feature"}'

Request body:

{
"value": "New Feature"
}

Response:

{
"success": true
}

Remove an item from an array by index.

DELETE /api/array/:path/:index

Example:

Terminal window
curl -X DELETE http://localhost:4185/api/array/features/2

Response:

{
"success": true
}

Change the order of items in an array.

PATCH /api/array/:path/reorder

Request body:

{
"from": 0,
"to": 2
}

Response:

{
"success": true
}

Add an event to a calendar field. An ID is auto-generated if not provided.

POST /api/calendar/:path/push

Example:

Terminal window
curl -X POST http://localhost:4185/api/calendar/events/push \
-H "Content-Type: application/json" \
-d '{"value": {"title": "Team Meeting", "start": "2025-04-01T10:00:00", "end": "2025-04-01T11:00:00", "allDay": false}}'

Request body:

{
"value": {
"title": "Team Meeting",
"start": "2025-04-01T10:00:00",
"end": "2025-04-01T11:00:00",
"allDay": false,
"description": "Weekly sync",
"location": "Room 3",
"color": "#4f46e5",
"url": "https://meet.example.com/123"
}
}

Response:

{
"success": true
}

Update an existing calendar event by ID.

PATCH /api/calendar/:path/:eventId

Example:

Terminal window
curl -X PATCH http://localhost:4185/api/calendar/events/abc-123 \
-H "Content-Type: application/json" \
-d '{"title": "Updated Meeting", "start": "2025-04-01T14:00:00"}'

Request body (partial update):

{
"title": "Updated Meeting",
"start": "2025-04-01T14:00:00"
}

Response:

{
"success": true
}

Remove an event from a calendar field by ID.

DELETE /api/calendar/:path/:eventId

Example:

Terminal window
curl -X DELETE http://localhost:4185/api/calendar/events/abc-123

Response:

{
"success": true,
"remaining": 4
}

Calendar events have the following structure:

interface CalendarEvent {
id: string; // Auto-generated UUID
title: string; // Event title (required)
start: string; // ISO date/datetime string (required)
end: string; // ISO date/datetime string (required)
allDay: boolean; // Whether the event spans full days
description?: string; // Optional event description
location?: string; // Optional event location
color?: string; // Optional hex color (e.g., "#4f46e5")
url?: string; // Optional URL associated with the event
props?: Record<string, any>; // Optional custom properties
}

Custom properties can be defined via the propsSchema field in metadata, allowing calendar fields to carry domain-specific data per event.

Subscribe to real-time schema updates.

GET /api/events

This endpoint returns an SSE stream. The server sends events whenever acms.json is modified:

event: schema-update
data: {"type": "schema-update"}

Example usage in JavaScript:

const eventSource = new EventSource('http://localhost:4185/api/events');
eventSource.addEventListener('schema-update', (event) => {
console.log('Schema updated, refetching...');
// Refetch content from /api/content
});

All endpoints return standard error responses:

{
"error": "Field not found",
"status": 404
}

Common HTTP status codes:

StatusMeaning
200Success
400Bad request (invalid path, missing body)
404Field not found
409Conflict (reserved field name)
500Internal server error

The dev server enables CORS for all origins, allowing requests from any frontend application running on any port during development.