The Schema API provides access to the content type registry. It lets you introspect the types defined in your project and sync schema changes from the CLI.
List Types
Returns all content types registered in the current project and environment,
including resolved field metadata.
Scope required: schema:read
Example request:
curl "https://cms.example.com/api/v1/schema" \
-H "X-MDCMS-Project: marketing-site" \
-H "X-MDCMS-Environment: production" \
-H "Authorization: Bearer mdcms_key_live_abc123"
Response:
{
"data": {
"types": [
{
"name": "Author",
"directory": "content/authors",
"localized": false,
"fields": {
"name": {
"kind": "string",
"required": true,
"nullable": false,
"default": null,
"reference": null,
"checks": [{ "type": "min", "value": 1 }]
},
"bio": {
"kind": "string",
"required": false,
"nullable": false,
"default": null,
"reference": null,
"checks": []
},
"website": {
"kind": "string",
"required": false,
"nullable": false,
"default": null,
"reference": null,
"checks": [{ "type": "url" }]
}
}
},
{
"name": "BlogPost",
"directory": "content/blog",
"localized": true,
"fields": {
"title": {
"kind": "string",
"required": true,
"nullable": false,
"default": null,
"reference": null,
"checks": [
{ "type": "min", "value": 1 },
{ "type": "max", "value": 200 }
]
},
"slug": {
"kind": "string",
"required": true,
"nullable": false,
"default": null,
"reference": null,
"checks": [{ "type": "regex", "value": "^[a-z0-9-]+$" }]
},
"author": {
"kind": "reference",
"required": true,
"nullable": false,
"default": null,
"reference": {
"targetType": "Author"
},
"checks": []
},
"publishedAt": {
"kind": "date",
"required": true,
"nullable": false,
"default": null,
"reference": null,
"checks": []
},
"tags": {
"kind": "array",
"required": false,
"nullable": false,
"default": [],
"reference": null,
"checks": [],
"items": {
"kind": "string",
"checks": []
}
}
}
}
],
"schemaHash": "sha256_abc123def456789"
}
}
Each field in the response includes the following properties:
| Property | Type | Description |
|---|
kind | string | The field’s data type: string, number, boolean, date, array, object, reference, enum. |
required | boolean | Whether the field must be present in frontmatter. |
nullable | boolean | Whether the field accepts null as a value. |
default | any | Default value applied when the field is omitted. null means no default. |
reference | object | null | For reference fields, contains targetType. null for non-reference fields. |
checks | array | Validation constraints derived from the Zod schema (e.g., min, max, regex, url, email). |
Get Type
Returns the full schema definition for a single content type.
Scope required: schema:read
Path Parameters
The content type name (e.g., BlogPost).
Example request:
curl "https://cms.example.com/api/v1/schema/BlogPost" \
-H "X-MDCMS-Project: marketing-site" \
-H "X-MDCMS-Environment: production" \
-H "Authorization: Bearer mdcms_key_live_abc123"
Response:
{
"data": {
"name": "BlogPost",
"directory": "content/blog",
"localized": true,
"fields": {
"title": {
"kind": "string",
"required": true,
"nullable": false,
"default": null,
"reference": null,
"checks": [
{ "type": "min", "value": 1 },
{ "type": "max", "value": 200 }
]
},
"slug": {
"kind": "string",
"required": true,
"nullable": false,
"default": null,
"reference": null,
"checks": [{ "type": "regex", "value": "^[a-z0-9-]+$" }]
},
"author": {
"kind": "reference",
"required": true,
"nullable": false,
"default": null,
"reference": {
"targetType": "Author"
},
"checks": []
},
"publishedAt": {
"kind": "date",
"required": true,
"nullable": false,
"default": null,
"reference": null,
"checks": []
},
"tags": {
"kind": "array",
"required": false,
"nullable": false,
"default": [],
"reference": null,
"checks": [],
"items": {
"kind": "string",
"checks": []
}
}
},
"schemaHash": "sha256_abc123def456789"
}
}
Error cases:
| Error Code | Cause |
|---|
SCHEMA_NOT_FOUND | The requested type name does not exist in the schema registry. |
Sync Schema
Push the current schema definition to the server. This is the endpoint called
by mdcms schema sync. The operation is idempotent — syncing the same schema
twice produces no changes.
Scope required: schema:write
Request Body
The raw configuration object from mdcms.config.ts, serialized as JSON. This
is stored for audit and debugging purposes.
The fully resolved schema with all field metadata, environment overlays
applied, and references validated. This is what the server uses for content
validation.
A deterministic hash of the resolved schema. Used by content write endpoints
to verify client-server schema consistency.
Example request:
curl -X PUT "https://cms.example.com/api/v1/schema/sync" \
-H "Content-Type: application/json" \
-H "X-MDCMS-Project: marketing-site" \
-H "X-MDCMS-Environment: production" \
-H "X-MDCMS-CSRF-Token: csrf_token_value" \
-H "Authorization: Bearer mdcms_key_live_abc123" \
-d '{
"rawConfigSnapshot": {
"project": "marketing-site",
"types": ["Author", "BlogPost"]
},
"resolvedSchema": {
"types": [
{
"name": "Author",
"directory": "content/authors",
"localized": false,
"fields": {
"name": { "kind": "string", "required": true, "nullable": false, "default": null, "reference": null, "checks": [{ "type": "min", "value": 1 }] }
}
},
{
"name": "BlogPost",
"directory": "content/blog",
"localized": true,
"fields": {
"title": { "kind": "string", "required": true, "nullable": false, "default": null, "reference": null, "checks": [{ "type": "min", "value": 1 }, { "type": "max", "value": 200 }] },
"slug": { "kind": "string", "required": true, "nullable": false, "default": null, "reference": null, "checks": [{ "type": "regex", "value": "^[a-z0-9-]+$" }] },
"author": { "kind": "reference", "required": true, "nullable": false, "default": null, "reference": { "targetType": "Author" }, "checks": [] },
"publishedAt": { "kind": "date", "required": true, "nullable": false, "default": null, "reference": null, "checks": [] },
"tags": { "kind": "array", "required": false, "nullable": false, "default": [], "reference": null, "checks": [], "items": { "kind": "string", "checks": [] } }
}
}
]
},
"schemaHash": "sha256_abc123def456789"
}'
Response:
{
"data": {
"synced": true,
"schemaHash": "sha256_abc123def456789",
"typesCount": 2,
"types": ["Author", "BlogPost"],
"syncedAt": "2026-01-20T10:00:00.000Z",
"syncedBy": "880e8400-e29b-41d4-a716-446655440002"
}
}
In practice, you should never call this endpoint directly. Use mdcms schema sync from the CLI, which reads your mdcms.config.ts, resolves the schema,
computes the hash, and sends the request.
Schema sync does not perform destructive migrations. If you remove a field
from the schema, existing documents that contain that field are not modified.
The field simply stops being validated and stops appearing in Studio forms.