# Blog API Documentation

**Base URL:** `https://sanad.work/staging/api` (staging) or `https://sanad.work/production/api` (production)

**Localization:** Send `Accept-Language: ar` header for Arabic, `Accept-Language: en` for English. Affects `title`, `content`, `question`, `answer` fields in responses.

**Standard Response Wrapper:**
All responses use this format:
```json
{
  "status": true,
  "message": "Success",
  "data": { ... }
}
```
Error responses:
```json
{
  "status": false,
  "message": "Error description",
  "errors": { ... }
}
```

---

## Data Models

### Blog
| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Blog ID |
| `title` | string | Blog title (localized based on Accept-Language header) |
| `image` | string (URL) | Full URL to blog cover image |
| `created_by` | object | `{ user: { user_id, user_name, user_image } }` |
| `created_at` | datetime | Creation timestamp |
| `blog_contents` | array | Array of BlogContent objects |
| `blog_faq` | array | Array of BlogFaq objects |

### BlogContent
| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Content section ID |
| `blog_id` | integer | Parent blog ID |
| `title` | string | Section title (localized) |
| `content` | array | Structured content array (localized) — see Content Structure below |
| `attachment` | string (URL) or null | Full URL to section attachment image |
| `video_url` | string (URL) or null | Video URL |
| `url` | string (URL) or null | External link URL |
| `content_type` | string | One of: `table`, `list`, `links` |

#### Content Structure (content_en / content_ar)
Each content field is a JSON array of sections:
```json
[
  {
    "title": "Section heading",
    "description": "Optional description text",
    "subtitle": "Optional subtitle",
    "values": [
      { "title": "Item label", "url": "https://..." }
    ]
  }
]
```
- When `content_type` = `links`, each `values[].url` should be provided
- When `content_type` = `table` or `list`, `values[].url` is optional

### BlogFaq
| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | FAQ ID |
| `blog_id` | integer | Parent blog ID |
| `question` | string | FAQ question (localized) |
| `answer` | string | FAQ answer (localized) |

---

## Public Endpoints (No Authentication Required)

### 1. List All Blogs
```
GET /blogs
```

**Query Parameters:**
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | No | Page number (default: 1) |

**Response:**
```json
{
  "status": true,
  "message": "Success",
  "data": {
    "items": [
      {
        "id": 1,
        "title": "Blog Title",
        "image": "https://sanad.work/staging/blogs/attachments/image.jpg",
        "created_by": {
          "user": {
            "user_id": 181,
            "user_name": "Admin",
            "user_image": "https://..."
          }
        },
        "created_at": "2025-04-12T00:00:00.000000Z",
        "blog_contents": [...],
        "blog_faq": [...]
      }
    ],
    "from": 1,
    "to": 15,
    "per": 15,
    "total": 40,
    "total_pages": 3,
    "current": 1,
    "next_page_url": "https://sanad.work/staging/api/blogs?page=2",
    "prev_page_url": null,
    "path": "https://sanad.work/staging/api/blogs"
  }
}
```

**Pagination Fields:**
| Field | Type | Description |
|-------|------|-------------|
| `items` | array | Array of blog objects for current page |
| `from` | integer | First item number on this page |
| `to` | integer | Last item number on this page |
| `per` | integer | Items per page |
| `total` | integer | Total number of blogs |
| `total_pages` | integer | Total number of pages |
| `current` | integer | Current page number |
| `next_page_url` | string or null | URL for next page |
| `prev_page_url` | string or null | URL for previous page |
| `path` | string | Base URL for pagination |

---

### 2. Show Single Blog
```
GET /blogs/show/{id}
```

**Parameters:**
| Param | Location | Type | Required | Description |
|-------|----------|------|----------|-------------|
| `id` | URL path | integer | Yes | Blog ID |

**Response:**
```json
{
  "status": true,
  "message": "Success",
  "data": {
    "id": 1,
    "title": "Blog Title",
    "image": "https://sanad.work/staging/blogs/attachments/image.jpg",
    "created_by": {
      "user": {
        "user_id": 181,
        "user_name": "Admin",
        "user_image": "https://..."
      }
    },
    "created_at": "2025-04-12T00:00:00.000000Z",
    "blog_contents": [
      {
        "id": 1,
        "blog_id": 1,
        "title": "Content Section Title",
        "content": [
          {
            "title": "Heading",
            "description": "Some text...",
            "subtitle": null,
            "values": [
              { "title": "Item 1", "url": null }
            ]
          }
        ],
        "attachment": "https://sanad.work/staging/blogs/attachments/photo.jpg",
        "video_url": null,
        "url": null,
        "content_type": "list"
      }
    ],
    "blog_faq": [
      {
        "id": 1,
        "blog_id": 1,
        "question": "What is Sanad?",
        "answer": "Sanad is an influencer marketing platform..."
      }
    ]
  }
}
```

**Error (404):**
```json
{
  "status": false,
  "message": "Blog not found",
  "errors": null
}
```

---

## Authenticated Endpoints (Sanctum Token Required)

**Headers Required:**
```
Authorization: Bearer {sanctum_token}
Content-Type: multipart/form-data  (for create/update with files)
Accept-Language: en|ar
```

These endpoints require a logged-in user with a verified email.

---

### 3. Create Blog
```
POST /blogs/store
```
**Content-Type:** `multipart/form-data`

**Body Parameters:**
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `title_en` | string | Yes | English title (max 255) |
| `title_ar` | string | Yes | Arabic title (max 255) |
| `image` | file | Yes | Cover image (jpg, png, max 20MB) |
| `contents` | array | Yes | At least 1 content section |
| `contents[0][title_en]` | string | Yes | English section title |
| `contents[0][title_ar]` | string | Yes | Arabic section title |
| `contents[0][content_type]` | string | Yes | `table`, `list`, or `links` |
| `contents[0][content_en]` | array | Yes | English structured content (see below) |
| `contents[0][content_ar]` | array | Yes | Arabic structured content (see below) |
| `contents[0][attachment]` | file | No | Section image (jpg, png, jpeg, max 20MB) |
| `contents[0][video_url]` | string | No | Video URL |
| `contents[0][url]` | string | No | External link URL |
| `blog_faq` | array | No | Optional FAQ items |
| `blog_faq[0][question_en]` | string | Yes* | English question (max 255) |
| `blog_faq[0][question_ar]` | string | Yes* | Arabic question (max 255) |
| `blog_faq[0][answer_en]` | string | Yes* | English answer (max 2000) |
| `blog_faq[0][answer_ar]` | string | Yes* | Arabic answer (max 2000) |

*Required when `blog_faq` array is provided.

**Content Structure (content_en/content_ar) — form-data format:**
```
contents[0][content_en][0][title] = "Section heading"
contents[0][content_en][0][description] = "Optional description"
contents[0][content_en][0][subtitle] = "Optional subtitle"
contents[0][content_en][0][values][0][title] = "Item label"
contents[0][content_en][0][values][0][url] = "https://example.com"
```

**Success Response (200):**
```json
{
  "status": true,
  "message": "Data saved successfully",
  "data": {
    "id": 5,
    "title": "Blog Title",
    "image": "https://...",
    "created_by": { "user": { ... } },
    "created_at": "2025-04-12T...",
    "blog_contents": [...],
    "blog_faq": [...]
  }
}
```

**Validation Error (422):**
```json
{
  "status": false,
  "message": "Validation error",
  "errors": {
    "title_en": ["The title en field is required."],
    "image": ["The image field is required."]
  }
}
```

---

### 4. Update Blog
```
POST /blogs/update/{id}
```
**Content-Type:** `multipart/form-data`

**Body Parameters:**
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `title_en` | string | Yes | English title (max 255) |
| `title_ar` | string | Yes | Arabic title (max 255) |
| `image` | file | No | New cover image (jpg, png, jpeg, max 20MB). Keeps current if omitted. |

**Note:** This only updates the blog's title and image. Use the separate content/FAQ endpoints below to manage sections.

**Success Response:**
```json
{
  "status": true,
  "message": "Data updated successfully",
  "data": []
}
```

---

### 5. Delete Blog
```
DELETE /blogs/delete/{id}
```

**Success Response:**
```json
{
  "status": true,
  "message": "Deleted successfully",
  "data": []
}
```

---

## Blog Content Endpoints (Auth Required)

### 6. List Blog Contents
```
GET /blogs/blog-contents/{blogId}
```

**Response:**
```json
{
  "status": true,
  "message": "Success",
  "data": [
    {
      "id": 1,
      "blog_id": 5,
      "title": "Section Title",
      "content": [{ "title": "...", "values": [...] }],
      "attachment": "https://...",
      "video_url": null,
      "url": null,
      "content_type": "list"
    }
  ]
}
```

---

### 7. Show Single Content
```
GET /blogs/show-content/{contentId}
```

**Response:**
```json
{
  "status": true,
  "message": "Success",
  "data": {
    "id": 1,
    "blog_id": 5,
    "title": "Section Title",
    "content": [...],
    "attachment": "https://...",
    "video_url": null,
    "url": null,
    "content_type": "list"
  }
}
```

---

### 8. Create Blog Content
```
POST /blogs/store-content/{blogId}
```
**Content-Type:** `multipart/form-data`

**Body Parameters:**
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `title_en` | string | Yes | English section title (max 255) |
| `title_ar` | string | Yes | Arabic section title (max 255) |
| `content_type` | string | Yes | `table`, `list`, or `links` |
| `content_en` | array | Yes | English structured content (same format as blog create) |
| `content_ar` | array | Yes | Arabic structured content (same format as blog create) |
| `attachment` | file | No | Section image (jpg, png, jpeg, max 20MB) |
| `video_url` | string (URL) | No | Video URL |
| `url` | string (URL) | No | External link |

**Success Response:**
```json
{
  "status": true,
  "message": "Data saved successfully",
  "data": { /* BlogContent object */ }
}
```

---

### 9. Update Blog Content
```
POST /blogs/update-content/{contentId}
```
Same body parameters as Create Content.

**Success Response:**
```json
{
  "status": true,
  "message": "Data updated successfully",
  "data": []
}
```

---

### 10. Delete Blog Content
```
DELETE /blogs/delete-content/{contentId}
```

**Success Response:**
```json
{
  "status": true,
  "message": "Deleted successfully",
  "data": []
}
```

---

## Blog FAQ Endpoints (Auth Required)

### 11. List Blog FAQs
```
GET /blogs/blog-faq/{blogId}
```

**Response:**
```json
{
  "status": true,
  "message": "Success",
  "data": [
    {
      "id": 1,
      "blog_id": 5,
      "question": "What is Sanad?",
      "answer": "Sanad is an influencer marketing platform..."
    }
  ]
}
```

---

### 12. Show Single FAQ
```
GET /blogs/show-faq/{faqId}
```

**Response:**
```json
{
  "status": true,
  "message": "Success",
  "data": {
    "id": 1,
    "blog_id": 5,
    "question": "What is Sanad?",
    "answer": "Sanad is..."
  }
}
```

---

### 13. Create Blog FAQ
```
POST /blogs/store-faq/{blogId}
```
**Content-Type:** `application/json` or `multipart/form-data`

**Body:**
```json
{
  "question_en": "What is Sanad?",
  "question_ar": "ما هو سند؟",
  "answer_en": "Sanad is an influencer marketing platform...",
  "answer_ar": "سند هو منصة تسويق عبر المؤثرين..."
}
```

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `question_en` | string | Yes | English question (max 255) |
| `question_ar` | string | Yes | Arabic question (max 255) |
| `answer_en` | string | Yes | English answer (max 2000) |
| `answer_ar` | string | Yes | Arabic answer (max 2000) |

**Success Response:**
```json
{
  "status": true,
  "message": "Data saved successfully",
  "data": { /* BlogFaq object */ }
}
```

---

### 14. Update Blog FAQ
```
POST /blogs/update-faq/{faqId}
```
Same body as Create FAQ.

**Success Response:**
```json
{
  "status": true,
  "message": "Data updated successfully",
  "data": []
}
```

---

### 15. Delete Blog FAQ
```
DELETE /blogs/delete-faq/{faqId}
```

**Success Response:**
```json
{
  "status": true,
  "message": "Deleted successfully",
  "data": []
}
```

---

## API Route Summary

| # | Method | Path | Auth | Description |
|---|--------|------|------|-------------|
| 1 | GET | `/blogs` | No | List all blogs (paginated) |
| 2 | GET | `/blogs/show/{id}` | No | Show single blog with contents + FAQ |
| 3 | POST | `/blogs/store` | Yes | Create blog with contents + FAQ |
| 4 | POST | `/blogs/update/{id}` | Yes | Update blog title/image |
| 5 | DELETE | `/blogs/delete/{id}` | Yes | Delete blog |
| 6 | GET | `/blogs/blog-contents/{blogId}` | Yes | List blog content sections |
| 7 | GET | `/blogs/show-content/{contentId}` | Yes | Show single content section |
| 8 | POST | `/blogs/store-content/{blogId}` | Yes | Add content section to blog |
| 9 | POST | `/blogs/update-content/{contentId}` | Yes | Update content section |
| 10 | DELETE | `/blogs/delete-content/{contentId}` | Yes | Delete content section |
| 11 | GET | `/blogs/blog-faq/{blogId}` | Yes | List blog FAQs |
| 12 | GET | `/blogs/show-faq/{faqId}` | Yes | Show single FAQ |
| 13 | POST | `/blogs/store-faq/{blogId}` | Yes | Add FAQ to blog |
| 14 | POST | `/blogs/update-faq/{faqId}` | Yes | Update FAQ |
| 15 | DELETE | `/blogs/delete-faq/{faqId}` | Yes | Delete FAQ |

---

## Frontend Integration Notes

1. **Public Blog Page:** Use endpoints #1 and #2 (no auth needed). The list endpoint includes `blog_contents` and `blog_faq` for each blog.

2. **Admin CMS Panel:** Use endpoints #3-15 with Sanctum bearer token. Auth requires a verified email.

3. **Image URLs:** All image URLs (`image`, `attachment`) are returned as full absolute URLs. Use them directly in `<img>` tags.

4. **Localization:** The API returns localized fields (`title`, `content`, `question`, `answer`) based on the `Accept-Language` header. The raw bilingual fields (`title_en`/`title_ar`, etc.) are NOT in the response — only the localized version.

5. **Content Types — how to render:**
   - `table` — Render content as a data table. Each `content[]` item is a section with `title` as column/row header and `values[]` as rows/cells.
   - `list` — Render content as a bulleted/numbered list. Each `values[].title` is a list item.
   - `links` — Render content as clickable links. Each `values[]` has a `title` (display text) and `url` (link destination).

6. **File Uploads:** Blog create and content create/update require `multipart/form-data`. Do NOT use `application/json` for these endpoints.

7. **Pagination:** Use `?page=N` for navigation. Key fields: `current` (current page), `total_pages` (last page), `total` (total items), `next_page_url` / `prev_page_url` (null when at start/end).
