791 lines
13 KiB
Markdown
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
|