# CMS Blog API Documentation

## Overview
The Blog API provides access to blog posts, categories, and tags. All endpoints require company authentication and support filtering, searching, and pagination. The API includes post visibility controls and view tracking.

## Authentication
All requests require the following headers:

| Header | Required | Description |
|--------|----------|-------------|
| `X-Company-Hash` | Yes | Unique company identifier |
| `Accept` | Yes | `application/json` |

**Missing or invalid company hash returns `422 Unprocessable Entity`**

---

## Endpoints

### 1. List All Blog Posts (Paginated)
```
GET /api/blogs
```

Returns a paginated list of all blog posts for the authenticated company with filtering, searching, and sorting options.

**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `page` | integer | 1 | Page number for pagination |
| `per_page` | integer | 20 | Items per page (max 100) |
| `search` | string | - | Search in title, excerpt, and content |
| `status` | string | - | Filter by status (1=published, 2=draft, 3=deleted) |
| `category_id` | integer | - | Filter by category ID |
| `tag_id` | integer | - | Filter by tag ID |
| `author_id` | integer | - | Filter by author ID |
| `featured` | boolean | - | Filter featured posts only |
| `include_private` | boolean | false | Include private posts |
| `sort` | string | `created_at` | Sort by: `title`, `publish_on`, `post_hits`, `created_at` |
| `order` | string | `desc` | Sort order: `asc` or `desc` |

**Response:**
```json
{
  "success": true,
  "message": "Blog posts fetched successfully",
  "data": {
    "posts": [
      {
        "id": 1,
        "title": "Getting Started with Our Platform",
        "slug": "getting-started-with-our-platform",
        "excerpt": "Learn how to get started with our amazing platform...",
        "status": "1",
        "visibility": "Pu",
        "feature_image": "https://example.com/storage/post-images/image.jpg",
        "is_featured": true,
        "publish_on": "2026-01-15T10:00:00Z",
        "post_hits": 245,
        "url": "https://example.com/blog/getting-started-with-our-platform",
        "author": {
          "id": 1,
          "name": "John Doe",
          "email": "john@example.com"
        },
        "category": {
          "id": 2,
          "name": "Tutorials"
        },
        "tags": [
          {
            "id": 5,
            "name": "Getting Started"
          },
          {
            "id": 8,
            "name": "Guide"
          }
        ],
        "created_at": "2026-01-10T14:30:00Z",
        "updated_at": "2026-01-15T09:20:00Z"
      }
    ],
    "pagination": {
      "current_page": 1,
      "per_page": 20,
      "total": 42,
      "last_page": 3
    }
  }
}
```

**Example Requests:**
```bash
# Get featured posts
GET /api/blogs?featured=true

# Search and filter
GET /api/blogs?search=tutorial&category_id=2&status=1

# Get posts by author with sorting
GET /api/blogs?author_id=1&sort=post_hits&order=desc
```

---

### 2. Get Blog Post by Slug
```
GET /api/blogs/{slug}
```

Retrieves a single blog post with full content and metadata by its slug. Automatically increments the post view count.

**Path Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `slug` | string | Yes | Post slug (URL-friendly identifier) |

**Query Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `include_private` | boolean | No | Include private posts |
| `password` | string | No | Password for password-protected posts |

**Response:**
```json
{
  "success": true,
  "message": "Blog post fetched successfully",
  "data": {
    "post": {
      "id": 1,
      "title": "Getting Started with Our Platform",
      "slug": "getting-started-with-our-platform",
      "excerpt": "Learn how to get started with our amazing platform...",
      "elements": [
        {
          "company_id": 1,
          "type_id": 1,
          "type": "posts",
          "type_class": "App\\Models\\Post",
          "theme": "light",
          "element_title": "Introduction Section",
          "element_sub_title": null,
          "element_id": "intro-section",
          "element_category": "Hero",
          "element_base": null,
          "element_icon": null,
          "content": {
            "text": "Welcome to our platform",
            "background_color": "#ffffff"
          },
          "is_visible": 1,
          "status": 1
        }
      ],
      "content_json": {
        "blocks": [
          {
            "type": "paragraph",
            "data": {
              "text": "This is the main content of the blog post..."
            }
          }
        ]
      },
      "status": "1",
      "visibility": "Pu",
      "feature_image": "https://example.com/storage/post-images/image.jpg",
      "is_featured": true,
      "publish_on": "2026-01-15T10:00:00Z",
      "post_hits": 246,
      "url": "https://example.com/blog/getting-started-with-our-platform",
      "meta": {
        "focus_keyword": "platform tutorial",
        "reading_time": "5 minutes"
      },
      "seo": {
        "page_title": "Getting Started with Our Platform - Blog",
        "meta_keywords": "platform, tutorial, getting started",
        "meta_description": "Learn how to get started with our amazing platform...",
        "content_url": "https://example.com/blog/getting-started-with-our-platform"
      },
      "author": {
        "id": 1,
        "name": "John Doe",
        "email": "john@example.com",
        "avatar": "https://example.com/storage/users/avatar.jpg"
      },
      "category": {
        "id": 2,
        "name": "Tutorials",
        "slug": "tutorials"
      },
      "tags": [
        {
          "id": 5,
          "name": "Getting Started",
          "slug": "getting-started"
        },
        {
          "id": 8,
          "name": "Guide",
          "slug": "guide"
        }
      ],
      "created_at": "2026-01-10T14:30:00Z",
      "updated_at": "2026-01-15T09:20:00Z"
    }
  }
}
```

**Example Requests:**
```bash
# Get a public post
GET /api/blogs/my-first-post

# Get a private post (with permission)
GET /api/blogs/private-post?include_private=1

# Access password-protected post
GET /api/blogs/protected-post?password=mypassword123
```

---

### 3. Get Categories and Tags
```
GET /api/blog/categories
```

Retrieves all blog categories and tags with their post counts. Only includes published and public posts in counts.

**Response:**
```json
{
  "success": true,
  "message": "Categories and tags fetched successfully",
  "data": {
    "categories": [
      {
        "id": 1,
        "name": "News",
        "slug": "news",
        "description": "Latest news and updates",
        "posts_count": 12
      },
      {
        "id": 2,
        "name": "Tutorials",
        "slug": "tutorials",
        "description": "Step-by-step guides and tutorials",
        "posts_count": 8
      },
      {
        "id": 3,
        "name": "Tips & Tricks",
        "slug": "tips-tricks",
        "description": "Helpful tips and tricks",
        "posts_count": 5
      }
    ],
    "tags": [
      {
        "id": 1,
        "name": "Getting Started",
        "slug": "getting-started",
        "posts_count": 3
      },
      {
        "id": 2,
        "name": "Best Practices",
        "slug": "best-practices",
        "posts_count": 7
      },
      {
        "id": 3,
        "name": "Guide",
        "slug": "guide",
        "posts_count": 5
      },
      {
        "id": 4,
        "name": "Advanced",
        "slug": "advanced",
        "posts_count": 2
      }
    ]
  }
}
```

---

## Data Models

### Post Object
| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Post ID |
| `title` | string | Post title |
| `slug` | string | URL-friendly slug |
| `excerpt` | string | Short post preview |
| `elements` | array | Editor elements (magic editor) |
| `content_json` | object | JSON-formatted content |
| `status` | string | Publication status (1=published, 2=draft) |
| `visibility` | string | Visibility level (Pu=public, Pr=private, PP=password-protected) |
| `feature_image` | string | Featured image URL |
| `is_featured` | boolean | Featured post flag |
| `publish_on` | datetime | Publication date/time |
| `post_hits` | integer | View count |
| `url` | string | Full post URL |
| `meta` | object | Custom metadata |
| `seo` | object | SEO information |
| `author` | object | Author details |
| `category` | object | Post category |
| `tags` | array | Post tags |
| `created_at` | datetime | Creation timestamp |
| `updated_at` | datetime | Last update timestamp |

### Category Object
| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Category ID |
| `name` | string | Category name |
| `slug` | string | Category slug |
| `description` | string | Category description |
| `posts_count` | integer | Number of published posts |

### Tag Object
| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Tag ID |
| `name` | string | Tag name |
| `slug` | string | Tag slug |
| `posts_count` | integer | Number of published posts |

### Author Object
| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | User ID |
| `name` | string | Author name |
| `email` | string | Author email |
| `avatar` | string | Avatar image URL |

---

## Status Codes

| Code | Meaning | Description |
|------|---------|-------------|
| `200` | OK | Request succeeded |
| `403` | Forbidden | Access denied (private/password-protected) |
| `404` | Not Found | Post, category, or tag not found |
| `422` | Unprocessable Entity | Missing or invalid X-Company-Hash header |

---

## Error Responses

All error responses follow this format:

```json
{
  "success": false,
  "message": "Error message description",
  "errors": []
}
```

**Examples:**

Missing company hash:
```json
{
  "success": false,
  "message": "Missing or invalid X-Company-Hash header.",
  "errors": []
}
```

Post not found:
```json
{
  "success": false,
  "message": "Blog post not found",
  "errors": []
}
```

Access denied:
```json
{
  "success": false,
  "message": "Access denied",
  "errors": []
}
```

---

## Filtering & Search Examples

### By Category
```
GET /api/blogs?category_id=2
```

### By Tag
```
GET /api/blogs?tag_id=5
```

### By Author
```
GET /api/blogs?author_id=1
```

### Featured Posts Only
```
GET /api/blogs?featured=true
```

### Combined Filters
```
GET /api/blogs?search=tutorial&category_id=2&author_id=1&sort=post_hits&order=desc&per_page=50
```

### Sort by Popularity
```
GET /api/blogs?sort=post_hits&order=desc
```

### Most Recent
```
GET /api/blogs?sort=created_at&order=desc
```

---

## Rate Limiting
Currently no rate limiting is applied to these endpoints. Future versions may include rate limiting based on API key or IP address.

---

## Caching
Posts are not cached at the API level. Each request fetches fresh data from the database. Consider implementing client-side caching for optimal performance.

---

## Visibility Levels

- **Public (Pu)**: Visible to all users
- **Private (Pr)**: Visible only with `include_private=1` parameter
- **Password Protected (PP)**: Requires `password` parameter in query string

---

## Field-Level Content Support

The Blog API supports rich content through multiple formats:

1. **Editor Elements** (`elements`): Custom page builder elements
2. **Content JSON** (`content_json`): Structured JSON content format
3. **Featured Images**: High-quality featured image URLs

---

## Response Headers

All successful responses include:
```
Content-Type: application/json
```

---

## Best Practices

1. **Use pagination**: Always specify `per_page` to control response size
2. **Filter when possible**: Use category, tag, or author filters to reduce payload
3. **Handle errors gracefully**: Check `success` field in response
4. **Cache results**: Implement client-side caching for frequently accessed posts
5. **Use appropriate slugs**: Slugs are the preferred way to access posts (more stable than IDs)

