A headless Laravel CMS with full SEO support. All endpoints are available under /api/v1/.
TuxCMS uses Laravel Sanctum for API authentication. All protected endpoints require a Bearer token.
POST /api/v1/auth/register
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com",
"password": "password123",
"password_confirmation": "password123"
}
Response: 201 Created
{
"data": {
"id": 1,
"name": "John Doe",
"email": "john@example.com",
...
},
"token": "TOKEN_HERE",
"message": "User registered successfully"
}
POST /api/v1/auth/login
Content-Type: application/json
{
"email": "john@example.com",
"password": "password123"
}
Response: 200 OK
{
"data": {...},
"token": "TOKEN_HERE",
"message": "Login successful"
}
POST /api/v1/auth/logout
Authorization: Bearer TOKEN_HERE
Response: 200 OK
{
"message": "Logged out successfully"
}
GET /api/v1/auth/me
Authorization: Bearer TOKEN_HERE
Response: 200 OK
{
"data": {
"id": 1,
"name": "John Doe",
"email": "john@example.com",
...
}
}
GET /api/v1/posts
Query Parameters:
- page=1 (pagination)
- per_page=15
- published=true (only published posts)
- status=published|draft|scheduled|archived
- type=post|page|custom
- category=slug
- tag=name
- author_id=1
- search=keyword
- include=author,categories,tags,seo
Response: 200 OK
{
"data": [
{
"id": 1,
"title": "Post Title",
"slug": "post-title",
"content": "...",
"excerpt": "...",
"featured_image": "url",
"status": "published",
"type": "post",
"published_at": "2024-03-13T00:00:00Z",
"author": {...},
"categories": [...],
"tags": ["tag1", "tag2"],
"seo": {...},
"meta_tags": {...},
"og_tags": {...},
"twitter_tags": {...},
"canonical_url": "https://example.com/post-title",
"created_at": "2024-03-13T00:00:00Z",
"updated_at": "2024-03-13T00:00:00Z"
}
],
"meta": {
"total": 50,
"per_page": 15,
"current_page": 1,
"last_page": 4
},
"links": {
"first": "http://example.com/api/v1/posts?page=1",
"last": "http://example.com/api/v1/posts?page=4",
"prev": null,
"next": "http://example.com/api/v1/posts?page=2"
}
}
GET /api/v1/posts/{slug-or-id}
Query Parameters:
- include=author,categories,tags,seo
Response: 200 OK
{
"data": {...}
}
GET /api/v1/categories
Query Parameters:
- parent_id=1
- search=keyword
- include=parent,children,seo
- sort=name|order|created_at
Response: 200 OK
{
"data": [
{
"id": 1,
"name": "Category Name",
"slug": "category-name",
"description": "...",
"order": 0,
"parent_id": null,
"parent": null,
"children": [...],
"seo": {...},
"meta_tags": {...},
"canonical_url": "https://example.com/category-name",
"created_at": "2024-03-13T00:00:00Z",
"updated_at": "2024-03-13T00:00:00Z"
}
]
}
GET /api/v1/categories/tree
Response: 200 OK
{
"data": [
{
"id": 1,
"name": "Parent Category",
"children": [
{
"id": 2,
"name": "Child Category",
"children": [...]
}
]
}
]
}
GET /api/v1/categories/{slug-or-id}
GET /api/v1/posts/{post_id}/comments
Query Parameters:
- limit=20 (alternative to pagination)
Response: 200 OK
{
"data": [
{
"id": 1,
"body": "Great post!",
"author_name": "John",
"author_email": "john@example.com",
"status": "approved",
"post_id": 1,
"parent_id": null,
"user": null,
"replies": [...],
"created_at": "2024-03-13T00:00:00Z",
"updated_at": "2024-03-13T00:00:00Z"
}
]
}
POST /api/v1/comments
Content-Type: application/json
{
"body": "Great post!",
"author_name": "John Doe",
"author_email": "john@example.com",
"post_id": 1,
"parent_id": null
}
Response: 201 Created
{
"data": {...},
"message": "Comment submitted. It will be visible once approved."
}
GET /api/v1/menus
Include: items
Response: 200 OK
{
"data": [
{
"id": 1,
"name": "Main Menu",
"slug": "main-menu",
"location": "header",
"items": [
{
"id": 1,
"title": "Home",
"url": "https://example.com",
"target": "_self",
"order": 0,
"type": "custom",
"children": [...]
}
]
}
]
}
GET /api/v1/menus/{slug-or-id}
GET /api/v1/settings
Query Parameters:
- group=site|seo|social|email
Response: 200 OK
{
"data": [
{
"id": 1,
"key": "site_name",
"value": "TuxCMS",
"group": "site"
}
]
}
GET /api/v1/settings/grouped
Response: 200 OK
{
"data": {
"site": {
"site_name": "TuxCMS",
"site_description": "...",
...
},
"seo": {...},
"social": {...}
}
}
GET /api/v1/settings/{key}
GET /api/v1/seo/meta-tags
Query Parameters:
- slug=post-slug (required)
- type=post|category (required)
Response: 200 OK
{
"meta_tags": {
"title": "Post Title",
"description": "Meta description...",
"keywords": "keyword1, keyword2",
"canonical": "https://example.com/post-title",
"robots": "index, follow"
},
"og_tags": {
"og:title": "Post Title",
"og:description": "...",
"og:image": "https://example.com/image.jpg",
"og:type": "article",
"og:url": "https://example.com/post-title"
},
"twitter_tags": {
"twitter:card": "summary_large_image",
"twitter:title": "Post Title",
"twitter:description": "...",
"twitter:image": "https://example.com/image.jpg"
},
"schema_markup": {
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "Post Title",
...
}
}
GET /api/v1/search
Query Parameters:
- q=search-term (required)
- limit=20 (optional)
Response: 200 OK
{
"data": [
{
"id": 1,
"title": "Matching Post",
...
}
],
"meta": {...},
"links": {...}
}
GET /api/v1/sitemap.xml
Response: 200 OK (Content-Type: application/xml)
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com/api/v1/posts</loc>
<lastmod>2024-03-13T00:00:00+00:00</lastmod>
<changefreq>weekly</changefreq>
</url>
...
</urlset>
GET /api/v1/media
Query Parameters:
- page=1
- per_page=15
- collection=featured_image|gallery
- search=filename
Response: 200 OK
{
"data": [
{
"id": 1,
"name": "image",
"file_name": "image.jpg",
"mime_type": "image/jpeg",
"size": 25600,
"custom_properties": {
"alt_text": "Image alt text",
"caption": "Image caption"
},
"url": "https://example.com/storage/posts/1/image.jpg",
"collection_name": "featured_image",
"created_at": "2024-03-13T00:00:00Z"
}
],
"meta": {...}
}
GET /api/v1/media/{id}
All protected endpoints require Bearer token authentication:
Authorization: Bearer YOUR_TOKEN_HERE
POST /api/v1/posts
PUT /api/v1/posts/{id}
DELETE /api/v1/posts/{id}
POST /api/v1/categories
PUT /api/v1/categories/{id}
DELETE /api/v1/categories/{id}
GET /api/v1/comments/{id}
PUT /api/v1/comments/{id}
DELETE /api/v1/comments/{id}
POST /api/v1/menus
PUT /api/v1/menus/{id}
DELETE /api/v1/menus/{id}
POST /api/v1/settings
PUT /api/v1/settings/{key}
DELETE /api/v1/settings/{key}
GET /api/v1/seo
PUT /api/v1/seo
POST /api/v1/media (upload file)
DELETE /api/v1/media/{id}
All responses are in JSON format with consistent structure:
{
"data": {...},
"message": "Success message (optional)"
}{
"message": "Error message",
"errors": {
"field_name": ["Error detail 1", "Error detail 2"]
}
}Common HTTP Status Codes:
200 OK- Success201 Created- Resource created204 No Content- Deleted successfully400 Bad Request- Invalid input401 Unauthorized- Authentication required403 Forbidden- Permission denied404 Not Found- Resource not found422 Unprocessable Entity- Validation error500 Internal Server Error- Server error
List endpoints support pagination:
Query Parameters:
page- Page number (default: 1)per_page- Items per page (default: 15, max: 100)
Response includes:
meta.total- Total itemsmeta.per_page- Items per pagemeta.current_page- Current pagemeta.last_page- Last page numberlinks.first- Link to first pagelinks.last- Link to last pagelinks.prev- Link to previous pagelinks.next- Link to next page
Posts endpoint supports advanced filtering:
GET /api/v1/posts?filter[status]=published&filter[author_id]=1&sort=-created_at
Available filters:
status- post statustype- post typeauthor_id- author IDcategory- category slugtag- tag namesearch- search term
Available sorts:
title,published_at,created_at,-published_at,-created_at
Use include parameter to load relationships:
GET /api/v1/posts?include=author,categories,tags,seo