# Tài Liệu API

**Dịch vụ**: mkt-whatsapp-service-net  
**Phiên bản**: v1.0  
**URL Cơ sở**: `/api/v1/whatsapp`

## Xác Thực

Tất cả endpoints (trừ webhooks) yêu cầu xác thực qua JWT token.

```bash
Authorization: Bearer <jwt_token>
```

## Định Dạng Phản Hồi

Tất cả phản hồi tuân theo cấu trúc này:

```json
{
  "success": true | false,
  "data": { ... },
  "error": "Thông báo lỗi" | null,
  "pagination": { ... } | null
}
```

---

## Webhooks

### Xác Minh Webhook

**GET** `/webhooks`

Xác minh thách thức từ WhatsApp.

**Tham Số Truy Vấn**:
- `hub.mode` (string) - Phải là "subscribe"
- `hub.verify_token` (string) - Token xác minh của bạn
- `hub.challenge` (string) - Chuỗi ngẫu nhiên để phản hồi lại

**Phản Hồi**:
```
(Plain text) giá trị hub.challenge
```

### Nhận Sự Kiện

**POST** `/webhooks`

Nhận sự kiện tin nhắn từ WhatsApp.

**Headers**:
- `X-Hub-Signature-256` - Chữ ký HMAC-SHA256

**Request Body**:
```json
{
  "object": "whatsapp_business_account",
  "entry": [{
    "id": "123456",
    "changes": [{
      "value": {
        "messaging_product": "whatsapp",
        "metadata": {
          "phone_number_id": "123456789"
        },
        "messages": [{
          "from": "84901234567",
          "id": "wamid.xxx",
          "timestamp": "1704000000",
          "type": "text",
          "text": {
            "body": "Xin chào"
          }
        }]
      }
    }]
  }]
}
```

**Phản Hồi**:
```json
{
  "success": true
}
```

---

## Tài Khoản WhatsApp

### Kết Nối Tài Khoản

**POST** `/accounts`

Kết nối Tài Khoản Doanh Nghiệp WhatsApp.

**Request**:
```json
{
  "shopId": "550e8400-e29b-41d4-a716-446655440000",
  "phoneNumberId": "123456789",
  "accessToken": "EAAxxxxx",
  "webhookUrl": "https://yourdomain.com/api/v1/whatsapp/webhooks"
}
```

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "accountId": "660e8400-e29b-41d4-a716-446655440000",
    "shopId": "550e8400-e29b-41d4-a716-446655440000",
    "phoneNumberId": "123456789",
    "status": "active",
    "messageTier": "tier_1",
    "connectedAt": "2026-01-18T10:00:00Z"
  }
}
```

### Lấy Thông Tin Tài Khoản

**GET** `/accounts/{shopId}`

Lấy thông tin tài khoản của cửa hàng.

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "accountId": "660e8400-e29b-41d4-a716-446655440000",
    "shopId": "550e8400-e29b-41d4-a716-446655440000",
    "phoneNumberId": "123456789",
    "webhookUrl": "https://yourdomain.com/api/v1/whatsapp/webhooks",
    "status": "active",
    "messageTier": "tier_2",
    "dailyLimit": 10000,
    "messagesUsedToday": 1523,
    "connectedAt": "2026-01-15T10:00:00Z"
  }
}
```

### Ngắt Kết Nối Tài Khoản

**DELETE** `/accounts/{shopId}`

Ngắt kết nối Tài Khoản Doanh Nghiệp WhatsApp.

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "message": "Ngắt kết nối tài khoản thành công"
  }
}
```

---

## Hội Thoại

### Danh Sách Hội Thoại

**GET** `/conversations`

Lấy danh sách hội thoại có phân trang.

**Tham Số Truy Vấn**:
- `shopId` (bắt buộc) - ID cửa hàng
- `status` (tùy chọn) - Lọc: `active`, `closed`, `expired`
- `assignedAgentId` (tùy chọn) - Lọc theo nhân viên
- `skip` (mặc định: 0) - Vị trí phân trang
- `take` (mặc định: 20, tối đa: 100) - Kích thước trang

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "conversations": [
      {
        "id": "conv-001",
        "shopId": "shop-001",
        "customerWaId": "84901234567",
        "customerName": "Nguyễn Văn A",
        "status": "active",
        "assignedAgentId": null,
        "lastMessageAt": "2026-01-18T10:30:00Z",
        "messageCount": 5,
        "tags": ["new-customer"],
        "createdAt": "2026-01-18T10:00:00Z"
      }
    ],
    "totalCount": 42
  },
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 42,
    "totalPages": 3
  }
}
```

### Lấy Thông Tin Hội Thoại

**GET** `/conversations/{conversationId}`

Lấy chi tiết hội thoại với tin nhắn.

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "id": "conv-001",
    "shopId": "shop-001",
    "customer": {
      "waId": "84901234567",
      "name": "Nguyễn Văn A",
      "tags": ["vip"]
    },
    "status": "active",
    "messages": [
      {
        "id": "msg-001",
        "whatsAppMessageId": "wamid.xxx",
        "direction": "inbound",
        "content": {
          "type": "text",
          "text": "Xin chào"
        },
        "status": "read",
        "timestamp": "2026-01-18T10:00:00Z"
      },
      {
        "id": "msg-002",
        "whatsAppMessageId": "wamid.yyy",
        "direction": "outbound",
        "content": {
          "type": "text",
          "text": "Xin chào! Chúng tôi có thể giúp gì cho bạn?"
        },
        "status": "delivered",
        "timestamp": "2026-01-18T10:00:15Z"
      }
    ],
    "createdAt": "2026-01-18T10:00:00Z",
    "expiresAt": "2026-01-19T10:00:00Z"
  }
}
```

### Gửi Tin Nhắn

**POST** `/conversations/{conversationId}/messages`

Gửi tin nhắn trong hội thoại.

**Request**:
```json
{
  "content": {
    "type": "text",
    "text": "Cảm ơn bạn đã liên hệ!"
  }
}
```

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "messageId": "msg-003",
    "whatsAppMessageId": "wamid.zzz",
    "status": "sent",
    "timestamp": "2026-01-18T10:05:00Z"
  }
}
```

**Tin Nhắn Media**:
```json
{
  "content": {
    "type": "image",
    "url": "https://example.com/product.jpg",
    "caption": "Xem sản phẩm này!"
  }
}
```

**Tin Nhắn Tương Tác**:
```json
{
  "content": {
    "type": "interactive",
    "interactive": {
      "type": "button",
      "body": {
        "text": "Chọn một tùy chọn:"
      },
      "action": {
        "buttons": [
          {"id": "yes", "title": "Có"},
          {"id": "no", "title": "Không"}
        ]
      }
    }
  }
}
```

### Gán Hội Thoại

**POST** `/conversations/{conversationId}/assign`

Gán hội thoại cho nhân viên.

**Request**:
```json
{
  "agentId": "agent-001"
}
```

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "conversationId": "conv-001",
    "assignedAgentId": "agent-001",
    "assignedAt": "2026-01-18T10:10:00Z"
  }
}
```

### Đóng Hội Thoại

**POST** `/conversations/{conversationId}/close`

Đóng hội thoại.

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "conversationId": "conv-001",
    "status": "closed",
    "closedAt": "2026-01-18T10:15:00Z"
  }
}
```

---

## Khách Hàng

### Danh Sách Khách Hàng

**GET** `/customers`

Lấy danh sách khách hàng có phân trang.

**Tham Số Truy Vấn**:
- `shopId` (bắt buộc)
- `search` (tùy chọn) - Tìm kiếm theo tên/số điện thoại
- `tags` (tùy chọn) - Lọc theo tags (phân cách bằng dấu phẩy)
- `skip` / `take` (phân trang)

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "customers": [
      {
        "id": "cust-001",
        "waId": "84901234567",
        "name": "Nguyễn Văn A",
        "tags": ["vip", "frequent-buyer"],
        "optInStatus": "opted_in",
        "conversationCount": 12,
        "lastContactedAt": "2026-01-18T10:00:00Z",
        "createdAt": "2026-01-01T00:00:00Z"
      }
    ],
    "totalCount": 150
  }
}
```

### Lấy Thông Tin Khách Hàng

**GET** `/customers/{waId}`

Lấy hồ sơ khách hàng.

**Tham Số Truy Vấn**:
- `shopId` (bắt buộc)

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "id": "cust-001",
    "waId": "84901234567",
    "shopId": "shop-001",
    "name": "Nguyễn Văn A",
    "profilePictureUrl": "https://...",
    "consent": {
      "status": "opted_in",
      "timestamp": "2026-01-01T10:00:00Z",
      "source": "whatsapp"
    },
    "tags": ["vip"],
    "customFields": {
      "city": "Hanoi",
      "preferredLanguage": "vi"
    },
    "stats": {
      "conversationCount": 12,
      "averageResponseTime": "5m",
      "lastPurchaseDate": "2026-01-15"
    }
  }
}
```

### Cập Nhật Tags Khách Hàng

**PUT** `/customers/{waId}/tags`

Thêm hoặc xóa tags khách hàng.

**Tham Số Truy Vấn**:
- `shopId` (bắt buộc)

**Request**:
```json
{
  "addTags": ["vip", "electronics-buyer"],
  "removeTags": ["new-customer"]
}
```

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "waId": "84901234567",
    "tags": ["vip", "electronics-buyer"]
  }
}
```

### Cập Nhật Trạng Thái Opt-In

**PUT** `/customers/{waId}/opt-in`

Cập nhật sự đồng ý của khách hàng.

**Request**:
```json
{
  "status": "opted_in",
  "source": "web"
}
```

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "waId": "84901234567",
    "consent": {
      "status": "opted_in",
      "timestamp": "2026-01-18T10:20:00Z",
      "source": "web"
    }
  }
}
```

---

## Luồng Tự Động

### Danh Sách Luồng

**GET** `/flows`

Lấy danh sách luồng tự động.

**Tham Số Truy Vấn**:
- `shopId` (bắt buộc)
- `isActive` (tùy chọn) - Lọc theo trạng thái

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "flows": [
      {
        "id": "flow-001",
        "flowName": "Chào Mừng Khách Hàng Mới",
        "triggerType": "keyword",
        "isActive": true,
        "executionCount": 523,
        "createdAt": "2026-01-10T00:00:00Z"
      }
    ]
  }
}
```

### Tạo Luồng

**POST** `/flows`

Tạo luồng tự động.

**Request**: Xem [Hướng Dẫn Tự Động](AUTOMATION_GUIDE.md#tạo-luồng)

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "flowId": "flow-002",
    "flowName": "FAQ Bot",
    "isActive": false
  }
}
```

### Cập Nhật Luồng

**PUT** `/flows/{flowId}`

Cập nhật cấu hình luồng.

### Kích Hoạt Luồng

**POST** `/flows/{flowId}/activate`

Bật luồng tự động.

### Vô Hiệu Hóa Luồng

**POST** `/flows/{flowId}/deactivate`

Tắt luồng tự động.

---

## AI Agents

### Tạo AI Agent

**POST** `/ai-agents`

Cấu hình chatbot AI.

**Request**: Xem [Hướng Dẫn AI Chatbot](AI_CHATBOT_GUIDE.md#tạo-ai-agent)

### Cập Nhật AI Agent

**PUT** `/ai-agents/{agentId}`

Cập nhật tính cách/prompts.

### Kích Hoạt AI Agent

**POST** `/ai-agents/{agentId}/activate`

Bật phản hồi AI.

### Kiểm Tra AI Agent

**POST** `/ai-agents/{agentId}/test`

Mô phỏng phản hồi AI.

**Request**:
```json
{
  "conversationHistory": [
    {"role": "user", "content": "Bạn có laptop nào tốt?"}
  ],
  "customerContext": {
    "name": "Nguyễn Văn A",
    "tags": ["vip"]
  }
}
```

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "generatedResponse": "Chúng tôi có nhiều laptop tuyệt vời! Bạn đang tìm laptop cho mục đích gì ạ? Gaming hay làm việc văn phòng?",
    "tokensUsed": {"prompt": 450, "completion": 120, "total": 570},
    "estimatedCost": 0.0154,
    "latencyMs": 1850
  }
}
```

---

## Phân Tích

### Thống Kê Tin Nhắn

**GET** `/analytics/messages`

Lấy số liệu về lượng tin nhắn.

**Tham Số Truy Vấn**:
- `shopId` (bắt buộc)
- `startDate` / `endDate` (ISO 8601)
- `groupBy` - `hour`, `day`, `week`

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "metrics": [
      {
        "date": "2026-01-18",
        "inboundCount": 245,
        "outboundCount": 298,
        "totalCount": 543
      }
    ],
    "summary": {
      "totalInbound": 2450,
      "totalOutbound": 2980,
      "averagePerDay": 543
    }
  }
}
```

### Số Liệu Hội Thoại

**GET** `/analytics/conversations`

Lấy số liệu hiệu suất hội thoại.

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "averageResponseTime": "2m 30s",
    "averageResolutionTime": "15m 45s",
    "automationResolutionRate": 0.65,
    "aiResolutionRate": 0.78,
    "humanHandoffRate": 0.22
  }
}
```

### Hiệu Suất Tự Động

**GET** `/analytics/automations`

Lấy thống kê thực thi luồng tự động.

**Phản Hồi**:
```json
{
  "success": true,
  "data": {
    "flows": [
      {
        "flowId": "flow-001",
        "flowName": "Welcome Bot",
        "executionCount": 523,
        "completionRate": 0.89,
        "averageSteps": 3.2,
        "fallbackRate": 0.11
      }
    ]
  }
}
```

---

## Mã Lỗi

| Mã | Thông Báo | Mô Tả |
|----|-----------|-------|
| 400 | Bad Request | Định dạng request không hợp lệ |
| 401 | Unauthorized | Thiếu hoặc token xác thực không hợp lệ |
| 404 | Not Found | Tài nguyên không tồn tại |
| 409 | Conflict | Tài nguyên trùng lặp |
| 422 | Validation Error | Vi phạm quy tắc nghiệp vụ |
| 429 | Rate Limit Exceeded | Quá nhiều yêu cầu |
| 500 | Internal Server Error | Lỗi máy chủ |

**Định Dạng Phản Hồi Lỗi**:
```json
{
  "success": false,
  "error": "Validation failed: Phone number is required",
  "details": {
    "field": "phoneNumberId",
    "code": "REQUIRED_FIELD"
  }
}
```

---

## Giới Hạn Tốc Độ

- **Public APIs**: 60 yêu cầu/phút mỗi cửa hàng
- **Webhooks**: Không giới hạn (nhưng phải phản hồi < 5s)
- **Analytics**: 10 yêu cầu/phút mỗi cửa hàng

## Xác Minh Chữ Ký Webhooks

Xác minh header `X-Hub-Signature-256`:

```javascript
const crypto = require('crypto');

const signature = req.headers['x-hub-signature-256'];
const payload = JSON.stringify(req.body);

const expectedSignature = 'sha256=' + 
  crypto.createHmac('sha256', APP_SECRET)
    .update(payload)
    .digest('hex');

if (signature !== expectedSignature) {
  throw new Error('Invalid signature');
}
```

## Phân Trang

Tất cả endpoints danh sách đều hỗ trợ phân trang:

**Request**:
```
GET /conversations?skip=20&take=20
```

**Phản Hồi**:
```json
{
  "pagination": {
    "page": 2,
    "limit": 20,
    "total": 150,
    "totalPages": 8
  }
}
```

## Changelog

### v1.0 (2026-01-18)
- Phát hành ban đầu
- Tích hợp WhatsApp Cloud API
- Luồng tự động
- AI chatbot
- Quản lý khách hàng
