Content Models API
REST API reference for managing content models in Laizy CMS.
Content Models API
Content model endpoints manage the schema definitions that structure your content. Each content model maps to a model block in your .laizy schema file and defines the fields, types, and constraints for a category of content.
Authentication
All content model endpoints require authentication via the Authorization header and project context via the x-laizy-project header:
Authorization: Bearer laizy_eyJhbGciOiJI...
x-laizy-project: <project-id>| Endpoint | Required Scope |
|---|---|
contentModel.list | content:read or admin |
contentModel.get | content:read or admin |
contentModel.exists | content:read or admin |
contentModel.create | admin |
contentModel.update | admin |
contentModel.delete | admin |
contentModel.createFromSchema | admin |
contentModel.list
List all content models in the current project.
Input
{
// No additional input required
// Project is resolved from the x-laizy-project header
}Response
Returns an array of content models:
[
{
id: string;
name: string; // "BlogPost"
schemaAST: ModelDefinition; // Parsed schema structure
projectId: string;
createdAt: Date;
updatedAt: Date;
}
]The schemaAST contains the full parsed model definition:
interface ModelDefinition {
type: 'model';
name: string;
fields: Array<{
name: string;
fieldType: 'String' | 'Int' | 'Float' | 'Boolean' | 'DateTime';
constraints: {
required?: boolean;
unique?: boolean;
default?: string | number | boolean;
maxLength?: number;
minLength?: number;
};
}>;
}Example with ManagementClient
const models = await client.listContentModels();
for (const model of models) {
console.log(`${model.name}: ${model.schemaAST.fields.length} fields`);
}Example with fetch
const response = await fetch(
'https://laizycms.com/api/trpc/contentModel.list?input={}',
{
headers: {
'Authorization': `Bearer ${apiToken}`,
'x-laizy-project': projectId,
'Content-Type': 'application/json',
},
},
);
const { result } = await response.json();
const models = result.data;contentModel.get
Fetch a single content model by name.
Input
{
name: string; // Required -- model name (e.g. "BlogPost")
}Response
Returns the content model or throws NOT_FOUND:
{
id: string;
name: string;
schemaAST: ModelDefinition;
projectId: string;
createdAt: Date;
updatedAt: Date;
}Example with ManagementClient
const model = await client.getContentModel('BlogPost');
if (model) {
console.log(`Fields: ${model.schemaAST.fields.map(f => f.name).join(', ')}`);
// Fields: title, content, status, slug
} else {
console.log('Model not found');
}Errors
| Code | Cause |
|---|---|
NOT_FOUND | Model does not exist in the project |
UNAUTHORIZED | Invalid or missing authentication |
contentModel.create
Create a new content model by providing a model name and its schema AST.
Input
{
name: string; // Model name (must match schemaAST.name)
schemaAST: ModelDefinition; // Full parsed model definition
}Response
Returns the created content model:
{
id: string;
name: string;
schemaAST: ModelDefinition;
projectId: string;
createdAt: Date;
updatedAt: Date;
}Example
const model = await fetch(
'https://laizycms.com/api/trpc/contentModel.create',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${apiToken}`,
'x-laizy-project': projectId,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Product',
schemaAST: {
type: 'model',
name: 'Product',
fields: [
{
name: 'title',
fieldType: 'String',
constraints: { required: true, maxLength: 200 },
},
{
name: 'price',
fieldType: 'Float',
constraints: { required: true },
},
{
name: 'inStock',
fieldType: 'Boolean',
constraints: { default: true },
},
],
},
}),
},
);Errors
| Code | Cause |
|---|---|
CONFLICT | A model with this name already exists |
BAD_REQUEST | Schema AST name does not match the provided name |
UNAUTHORIZED | Token does not have admin scope |
In practice, you rarely call contentModel.create directly. The laizy sync command handles model creation as part of the schema synchronization workflow, which also manages updates and deletions.
contentModel.update
Update an existing content model's schema definition.
Input
{
name: string; // Existing model name
schemaAST: ModelDefinition; // Updated model definition
}Response
Returns the updated content model.
Errors
| Code | Cause |
|---|---|
NOT_FOUND | Model does not exist |
BAD_REQUEST | Schema AST name does not match the provided name |
UNAUTHORIZED | Token does not have admin scope |
contentModel.delete
Delete a content model and its associated metadata. Content data associated with the model is not automatically deleted by this endpoint.
Input
{
name: string; // Model name to delete
}Response
{
success: boolean;
}Errors
| Code | Cause |
|---|---|
NOT_FOUND | Model does not exist |
UNAUTHORIZED | Token does not have admin scope |
Deleting a content model removes its schema definition. The laizy sync command handles model deletion as part of the full diff workflow and includes impact analysis to warn you about content entries that will be affected.
contentModel.exists
Check whether a content model exists in the current project without fetching its full definition.
Input
{
name: string; // Model name to check
}Response
{
exists: boolean;
}contentModel.createFromSchema
Create a content model from a raw .laizy schema string instead of a pre-parsed AST. The server parses the schema and creates the model.
Input
{
schemaContent: string; // Raw .laizy schema text
}Example
const model = await fetch(
'https://laizycms.com/api/trpc/contentModel.createFromSchema',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${apiToken}`,
'x-laizy-project': projectId,
'Content-Type': 'application/json',
},
body: JSON.stringify({
schemaContent: `model Product {
title: String {
required: true
maxLength: 200
}
price: Float {
required: true
}
}`,
}),
},
);Errors
| Code | Cause |
|---|---|
BAD_REQUEST | Schema parsing failed, empty schema, or multiple models in input |
CONFLICT | Model already exists |
UNAUTHORIZED | Token does not have admin scope |
This endpoint currently supports only single-model schemas. If the schema string contains multiple model blocks, it returns a BAD_REQUEST error.
Schema Sync vs. Direct API
Most content model management is handled through the laizy sync command, which uses the SchemaSyncOrchestrator under the hood. Direct API calls are useful for:
- Building custom tooling that manages schemas programmatically
- CI/CD pipelines that need to verify model state
- Admin dashboards that display schema information
For standard development workflows, prefer laizy sync over direct API calls -- it handles diffing, impact analysis, and safe migration in a single command.
Next Steps
- Schema Sync -- How the sync orchestrator uses these endpoints
- Content Data API -- CRUD operations on content entries
- Schema Syntax -- The
.laizyschema language reference