Files
Ho Ngoc Hai 76d75c753b Migrate
2026-05-23 18:37:02 +07:00

791 lines
13 KiB
Markdown

# API Documentation
**Service**: mkt-whatsapp-service-net
**Version**: v1.0
**Base URL**: `/api/v1/whatsapp`
## Authentication
All endpoints (except webhooks) require authentication via JWT token.
```bash
Authorization: Bearer <jwt_token>
```
## Response Format
All responses follow this structure:
```json
{
"success": true | false,
"data": { ... },
"error": "Error message" | null,
"pagination": { ... } | null
}
```
---
## Webhooks
### Verify Webhook
**GET** `/webhooks`
WhatsApp verification challenge.
**Query Parameters**:
- `hub.mode` (string) - Should be "subscribe"
- `hub.verify_token` (string) - Your verification token
- `hub.challenge` (string) - Random string to echo back
**Response**:
```
(Plain text) hub.challenge value
```
### Receive Events
**POST** `/webhooks`
Receive message events from WhatsApp.
**Headers**:
- `X-Hub-Signature-256` - HMAC-SHA256 signature
**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": "Hello"
}
}]
}
}]
}]
}
```
**Response**:
```json
{
"success": true
}
```
---
## WhatsApp Accounts
### Connect Account
**POST** `/accounts`
Connect a WhatsApp Business Account.
**Request**:
```json
{
"shopId": "550e8400-e29b-41d4-a716-446655440000",
"phoneNumberId": "123456789",
"accessToken": "EAAxxxxx",
"webhookUrl": "https://yourdomain.com/api/v1/whatsapp/webhooks"
}
```
**Response**:
```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"
}
}
```
### Get Account
**GET** `/accounts/{shopId}`
Get account details for a shop.
**Response**:
```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"
}
}
```
### Disconnect Account
**DELETE** `/accounts/{shopId}`
Disconnect WhatsApp Business Account.
**Response**:
```json
{
"success": true,
"data": {
"message": "Account disconnected successfully"
}
}
```
---
## Conversations
### List Conversations
**GET** `/conversations`
Get paginated list of conversations.
**Query Parameters**:
- `shopId` (required) - Shop ID
- `status` (optional) - Filter: `active`, `closed`, `expired`
- `assignedAgentId` (optional) - Filter by agent
- `skip` (default: 0) - Pagination offset
- `take` (default: 20, max: 100) - Page size
**Response**:
```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
}
}
```
### Get Conversation
**GET** `/conversations/{conversationId}`
Get conversation details with messages.
**Response**:
```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"
}
}
```
### Send Message
**POST** `/conversations/{conversationId}/messages`
Send a message in a conversation.
**Request**:
```json
{
"content": {
"type": "text",
"text": "Cảm ơn bạn đã liên hệ!"
}
}
```
**Response**:
```json
{
"success": true,
"data": {
"messageId": "msg-003",
"whatsAppMessageId": "wamid.zzz",
"status": "sent",
"timestamp": "2026-01-18T10:05:00Z"
}
}
```
**Media Message**:
```json
{
"content": {
"type": "image",
"url": "https://example.com/product.jpg",
"caption": "Check out this product!"
}
}
```
**Interactive Message**:
```json
{
"content": {
"type": "interactive",
"interactive": {
"type": "button",
"body": {
"text": "Choose an option:"
},
"action": {
"buttons": [
{"id": "yes", "title": "Yes"},
{"id": "no", "title": "No"}
]
}
}
}
}
```
### Assign Conversation
**POST** `/conversations/{conversationId}/assign`
Assign conversation to an agent.
**Request**:
```json
{
"agentId": "agent-001"
}
```
**Response**:
```json
{
"success": true,
"data": {
"conversationId": "conv-001",
"assignedAgentId": "agent-001",
"assignedAt": "2026-01-18T10:10:00Z"
}
}
```
### Close Conversation
**POST** `/conversations/{conversationId}/close`
Close a conversation.
**Response**:
```json
{
"success": true,
"data": {
"conversationId": "conv-001",
"status": "closed",
"closedAt": "2026-01-18T10:15:00Z"
}
}
```
---
## Customers
### List Customers
**GET** `/customers`
Get paginated customer list.
**Query Parameters**:
- `shopId` (required)
- `search` (optional) - Search by name/phone
- `tags` (optional) - Filter by tags (comma-separated)
- `skip` / `take` (pagination)
**Response**:
```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
}
}
```
### Get Customer
**GET** `/customers/{waId}`
Get customer profile.
**Query Parameters**:
- `shopId` (required)
**Response**:
```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"
}
}
}
```
### Update Customer Tags
**PUT** `/customers/{waId}/tags`
Add or remove customer tags.
**Query Parameters**:
- `shopId` (required)
**Request**:
```json
{
"addTags": ["vip", "electronics-buyer"],
"removeTags": ["new-customer"]
}
```
**Response**:
```json
{
"success": true,
"data": {
"waId": "84901234567",
"tags": ["vip", "electronics-buyer"]
}
}
```
### Update Opt-In Status
**PUT** `/customers/{waId}/opt-in`
Update customer consent.
**Request**:
```json
{
"status": "opted_in",
"source": "web"
}
```
**Response**:
```json
{
"success": true,
"data": {
"waId": "84901234567",
"consent": {
"status": "opted_in",
"timestamp": "2026-01-18T10:20:00Z",
"source": "web"
}
}
}
```
---
## Automation Flows
### List Flows
**GET** `/flows`
Get automation flows.
**Query Parameters**:
- `shopId` (required)
- `isActive` (optional) - Filter by status
**Response**:
```json
{
"success": true,
"data": {
"flows": [
{
"id": "flow-001",
"flowName": "Welcome New Customer",
"triggerType": "keyword",
"isActive": true,
"executionCount": 523,
"createdAt": "2026-01-10T00:00:00Z"
}
]
}
}
```
### Create Flow
**POST** `/flows`
Create automation flow.
**Request**: See [Automation Guide](AUTOMATION_GUIDE.md#creating-a-flow)
**Response**:
```json
{
"success": true,
"data": {
"flowId": "flow-002",
"flowName": "FAQ Bot",
"isActive": false
}
}
```
### Update Flow
**PUT** `/flows/{flowId}`
Update flow configuration.
### Activate Flow
**POST** `/flows/{flowId}/activate`
Enable automation flow.
### Deactivate Flow
**POST** `/flows/{flowId}/deactivate`
Disable automation flow.
---
## AI Agents
### Create AI Agent
**POST** `/ai-agents`
Configure AI chatbot.
**Request**: See [AI Chatbot Guide](AI_CHATBOT_GUIDE.md#creating-an-ai-agent)
### Update AI Agent
**PUT** `/ai-agents/{agentId}`
Update personality/prompts.
### Activate AI Agent
**POST** `/ai-agents/{agentId}/activate`
Enable AI responses.
### Test AI Agent
**POST** `/ai-agents/{agentId}/test`
Simulate AI response.
**Request**:
```json
{
"conversationHistory": [
{"role": "user", "content": "Bạn có laptop nào tốt?"}
],
"customerContext": {
"name": "Nguyễn Văn A",
"tags": ["vip"]
}
}
```
**Response**:
```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
}
}
```
---
## Analytics
### Message Statistics
**GET** `/analytics/messages`
Get message volume metrics.
**Query Parameters**:
- `shopId` (required)
- `startDate` / `endDate` (ISO 8601)
- `groupBy` - `hour`, `day`, `week`
**Response**:
```json
{
"success": true,
"data": {
"metrics": [
{
"date": "2026-01-18",
"inboundCount": 245,
"outboundCount": 298,
"totalCount": 543
}
],
"summary": {
"totalInbound": 2450,
"totalOutbound": 2980,
"averagePerDay": 543
}
}
}
```
### Conversation Metrics
**GET** `/analytics/conversations`
Get conversation performance metrics.
**Response**:
```json
{
"success": true,
"data": {
"averageResponseTime": "2m 30s",
"averageResolutionTime": "15m 45s",
"automationResolutionRate": 0.65,
"aiResolutionRate": 0.78,
"humanHandoffRate": 0.22
}
}
```
### Automation Performance
**GET** `/analytics/automations`
Get automation flow execution stats.
**Response**:
```json
{
"success": true,
"data": {
"flows": [
{
"flowId": "flow-001",
"flowName": "Welcome Bot",
"executionCount": 523,
"completionRate": 0.89,
"averageSteps": 3.2,
"fallbackRate": 0.11
}
]
}
}
```
---
## Error Codes
| Code | Message | Description |
|------|---------|-------------|
| 400 | Bad Request | Invalid request format |
| 401 | Unauthorized | Missing or invalid auth token |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Duplicate resource |
| 422 | Validation Error | Business rule violation |
| 429 | Rate Limit Exceeded | Too many requests |
| 500 | Internal Server Error | Server error |
**Error Response Format**:
```json
{
"success": false,
"error": "Validation failed: Phone number is required",
"details": {
"field": "phoneNumberId",
"code": "REQUIRED_FIELD"
}
}
```
---
## Rate Limits
- **Public APIs**: 60 requests/minute per shop
- **Webhooks**: No limit (but must respond < 5s)
- **Analytics**: 10 requests/minute per shop
## Webhooks Signature Verification
Verify `X-Hub-Signature-256` header:
```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');
}
```
## Pagination
All list endpoints support pagination:
**Request**:
```
GET /conversations?skip=20&take=20
```
**Response**:
```json
{
"pagination": {
"page": 2,
"limit": 20,
"total": 150,
"totalPages": 8
}
}
```
## Changelog
### v1.0 (2026-01-18)
- Initial release
- WhatsApp Cloud API integration
- Automation flows
- AI chatbot
- Customer management