Appendix D: API Endpoint Reference
Complete REST API endpoint documentation for Vibe CMS, including request/response formats, authentication requirements, and practical examples.
Overview
Vibe CMS provides two main APIs:
- Public API - Read-only access to published content (requires API key)
- Admin API - Full CRUD operations on collections, content, files, and locales (requires JWT authentication)
Base URLs:
- Production:
https://api.vibecms.com - Staging:
https://staging-api.vibecms.com
Authentication
Public API
Header:
X-API-Key: your-api-key
Example:
curl -H "X-API-Key: vibe_pk_abc123" https://api.vibecms.com/api/public/content
Admin API
Header:
Authorization: Bearer your-jwt-token
Example:
curl -H "Authorization: Bearer eyJhbGc..." https://api.vibecms.com/api/admin/collections
Collections API
List Collections
Endpoint:
GET /api/admin/collections
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
string | Yes | Project identifier |
limit |
number | No | Maximum items (default: 50) |
offset |
number | No | Pagination offset (default: 0) |
Response:
{
"data": [
{
"id": "uuid",
"slug": "blog-posts",
"name": "Blog Posts",
"description": "Article content",
"is_singleton": false,
"item_count": 42,
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-01T00:00:00Z"
}
],
"count": 1,
"limit": 50,
"offset": 0
}
Example:
curl -H "Authorization: Bearer TOKEN" \
"https://api.vibecms.com/api/admin/collections?project_id=proj-123"
Get Collection
Endpoint:
GET /api/admin/collections/{collection_slug}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
string (query) | Yes | Project identifier |
Response:
{
"data": {
"id": "uuid",
"slug": "blog-posts",
"name": "Blog Posts",
"description": "Article content",
"is_singleton": false,
"fields": [
{
"id": "field-uuid",
"name": "title",
"field_type": "text",
"interface_type": "input",
"is_required": true,
"sort_order": 1
}
]
}
}
Create Collection
Endpoint:
POST /api/admin/collections
Request Body:
{
"project_id": "proj-123",
"slug": "blog-posts",
"name": "Blog Posts",
"description": "Article content",
"is_singleton": false
}
Response: 201 Created
{
"data": {
"id": "uuid",
"slug": "blog-posts",
"name": "Blog Posts",
"description": "Article content",
"is_singleton": false
}
}
Example:
curl -X POST -H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"project_id": "proj-123",
"slug": "blog-posts",
"name": "Blog Posts"
}' \
https://api.vibecms.com/api/admin/collections
Update Collection
Endpoint:
PATCH /api/admin/collections/{collection_slug}
Request Body:
{
"project_id": "proj-123",
"name": "Blog Articles",
"description": "Updated description"
}
Response: 200 OK
Delete Collection
Endpoint:
DELETE /api/admin/collections/{collection_slug}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
string (query) | Yes | Project identifier |
Response: 204 No Content
Content Items API
List Content Items
Endpoint:
GET /api/admin/content/{collection_slug}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
string (query) | Yes | Project identifier |
limit |
number | No | Maximum items (default: 50) |
offset |
number | No | Pagination offset (default: 0) |
status |
string | No | Filter by status: draft, published, archived |
locale |
string | No | Filter by locale (default: project's default locale) |
Response:
{
"data": [
{
"id": "item-uuid",
"collection_slug": "blog-posts",
"status": "published",
"description": "First blog post",
"locales": ["en-US", "de-DE"],
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-01T00:00:00Z"
}
],
"count": 1,
"limit": 50,
"offset": 0
}
Get Content Item
Endpoint:
GET /api/admin/content/{collection_slug}/{item_id}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
string (query) | Yes | Project identifier |
locale |
string | No | Specific locale (default: all locales) |
Response:
{
"data": {
"id": "item-uuid",
"collection_slug": "blog-posts",
"status": "published",
"description": "First blog post",
"translations": [
{
"locale": "en-US",
"data": {
"title": "Hello World",
"content": "# Welcome\n\nThis is my first post.",
"slug": "hello-world"
},
"updated_at": "2025-01-01T00:00:00Z"
},
{
"locale": "de-DE",
"data": {
"title": "Hallo Welt",
"content": "# Willkommen\n\nDas ist mein erster Beitrag.",
"slug": "hallo-welt"
},
"updated_at": "2025-01-01T00:00:00Z"
}
]
}
}
Create Content Item
Endpoint:
POST /api/admin/content/{collection_slug}
Request Body:
{
"project_id": "proj-123",
"status": "draft",
"description": "New blog post"
}
Response: 201 Created
{
"data": {
"id": "item-uuid",
"collection_slug": "blog-posts",
"status": "draft",
"description": "New blog post",
"created_at": "2025-01-01T00:00:00Z"
}
}
Update Content Translation
Endpoint:
PUT /api/admin/content/{collection_slug}/{item_id}/{locale}
Request Body:
{
"project_id": "proj-123",
"data": {
"title": "Hello World",
"content": "# Welcome\n\nThis is my first post.",
"slug": "hello-world"
},
"status": "published"
}
Response: 200 OK
{
"success": true,
"message": "Translation updated successfully"
}
Delete Content Item
Endpoint:
DELETE /api/admin/content/{collection_slug}/{item_id}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
string (query) | Yes | Project identifier |
locale |
string | No | Delete specific locale only |
Response: 204 No Content
Files API
List Files
Endpoint:
GET /api/admin/files
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
string (query) | Yes | Project identifier |
folder_path |
string | No | Filter by folder (e.g., '/images') |
mime_type |
string | No | Filter by MIME type (e.g., 'image/') |
limit |
number | No | Maximum items (default: 50) |
offset |
number | No | Pagination offset (default: 0) |
Response:
{
"data": [
{
"id": "file-uuid",
"filename": "hero.jpg",
"mime_type": "image/jpeg",
"file_size": 1024000,
"folder_path": "/images",
"title": "Hero Image",
"alt_text": "Modern office",
"url": "https://cdn.vibecms.com/projects/proj-123/files/file-uuid",
"created_at": "2025-01-01T00:00:00Z"
}
],
"count": 1,
"limit": 50,
"offset": 0
}
Get File
Endpoint:
GET /api/admin/files/{file_id}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
string (query) | Yes | Project identifier |
Response:
{
"data": {
"id": "file-uuid",
"filename": "hero.jpg",
"mime_type": "image/jpeg",
"file_size": 1024000,
"width": 1920,
"height": 1080,
"folder_path": "/images",
"title": "Hero Image",
"alt_text": "Modern office workspace",
"caption": "Hero image for homepage",
"description": "High-res hero image",
"focus_keyword": "office workspace",
"url": "https://cdn.vibecms.com/projects/proj-123/files/file-uuid"
}
}
Upload File
Endpoint:
POST /api/admin/files/upload
Request (multipart/form-data):
Content-Type: multipart/form-data
- project_id: proj-123
- file: [binary file data]
- folder_path: /images
- title: Hero Image
- alt_text: Modern office
Response: 201 Created
{
"data": {
"id": "file-uuid",
"filename": "hero.jpg",
"mime_type": "image/jpeg",
"file_size": 1024000,
"url": "https://cdn.vibecms.com/projects/proj-123/files/file-uuid"
}
}
Update File Metadata
Endpoint:
PATCH /api/admin/files/{file_id}
Request Body:
{
"project_id": "proj-123",
"title": "Updated Title",
"alt_text": "Updated alt text",
"caption": "Updated caption",
"focus_keyword": "new keyword",
"folder_path": "/images/featured"
}
Response: 200 OK
Delete File
Endpoint:
DELETE /api/admin/files/{file_id}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
string (query) | Yes | Project identifier |
Response: 204 No Content
Locales API
List Locales
Endpoint:
GET /api/admin/locales
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
string (query) | Yes | Project identifier |
Response:
{
"data": [
{
"locale_code": "en-US",
"display_name": "English (US)",
"is_default": true,
"is_active": true
},
{
"locale_code": "de-DE",
"display_name": "German (Germany)",
"is_default": false,
"is_active": true
}
],
"count": 2
}
Create Locale
Endpoint:
POST /api/admin/locales
Request Body:
{
"project_id": "proj-123",
"locale_code": "fr-FR",
"display_name": "French (France)",
"is_active": true,
"is_default": false
}
Response: 201 Created
Update Locale
Endpoint:
PATCH /api/admin/locales/{locale_code}
Request Body:
{
"project_id": "proj-123",
"display_name": "French (France)",
"is_active": true,
"is_default": false
}
Response: 200 OK
Delete Locale
Endpoint:
DELETE /api/admin/locales/{locale_code}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id |
string (query) | Yes | Project identifier |
Response: 204 No Content
Public API
Get Published Content
Endpoint:
GET /api/public/content/{collection_slug}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
api_key |
string (header) | Yes | API Key |
locale |
string | No | Locale code (default: project's default) |
limit |
number | No | Maximum items (default: 50) |
offset |
number | No | Pagination offset (default: 0) |
Response:
{
"data": [
{
"id": "item-uuid",
"slug": "hello-world",
"title": "Hello World",
"content": "# Welcome\n\nThis is my first post.",
"published_at": "2025-01-01T00:00:00Z"
}
],
"count": 1,
"limit": 50,
"offset": 0
}
Get Published Item by Slug
Endpoint:
GET /api/public/content/{collection_slug}/{slug}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
api_key |
string (header) | Yes | API Key |
locale |
string | No | Locale code (default: project's default) |
Response:
{
"data": {
"id": "item-uuid",
"slug": "hello-world",
"title": "Hello World",
"content": "# Welcome\n\nThis is my first post.",
"published_at": "2025-01-01T00:00:00Z"
}
}
Error Responses
All endpoints return consistent error responses:
Format:
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message",
"details": {}
}
}
Common Error Codes:
VALIDATION_ERROR(400) - Invalid parametersUNAUTHORIZED(401) - Missing or invalid authenticationFORBIDDEN(403) - Insufficient permissionsNOT_FOUND(404) - Resource not foundCONFLICT(409) - Duplicate or conflicting dataUNPROCESSABLE_ENTITY(422) - Semantically invalid dataTOO_MANY_REQUESTS(429) - Rate limit exceededINTERNAL_SERVER_ERROR(500) - Server error
Pagination
All list endpoints support pagination:
curl -H "Authorization: Bearer TOKEN" \
"https://api.vibecms.com/api/admin/content/blog-posts?project_id=proj-123&limit=20&offset=40"
Response metadata:
{
"data": [...],
"count": 100,
"limit": 20,
"offset": 40,
"total": 100,
"has_more": true
}
Rate Limits
API rate limits per project:
- Public API: 1000 requests/hour
- Admin API: 100 requests/minute
Headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640000000
Webhooks (Advanced)
Vibe CMS supports webhooks for content events:
Available Events:
content.createdcontent.updatedcontent.publishedcontent.unpublishedcontent.deletedfile.uploadedfile.deleted
Webhook Payload:
{
"event": "content.published",
"project_id": "proj-123",
"timestamp": "2025-01-01T00:00:00Z",
"data": {
"id": "item-uuid",
"collection_slug": "blog-posts",
"status": "published"
}
}
See Also
- Appendix A: MCP Tools Reference - MCP tool documentation
- Appendix B: Error Codes & Solutions - Detailed error reference
- Chapter 2: Getting Started - Quick start guide
- TypeScript SDK Documentation - SDK usage examples