{
  "info": {
    "name": "MLHUB Middleware API Sandbox v2",
    "description": "Bộ API kiểm thử cho Middleware MLHUB v2 — cổng kết nối hệ sinh thái FizaHub và MLHUB Engine.\n\n## Thiết lập môi trường\nTạo một **Postman Environment** với 2 biến:\n| Biến | Giá trị mẫu | Ghi chú |\n|---|---|---|\n| `base_url` | `https://api-sandbox.mlhub.vn` | Đổi thành `http://localhost:3000` khi chạy local |\n| `api_key` | *(nhận từ MLHUB)* | **KHÔNG** điền vào đây — lưu trong Environment |\n\n## Cấu trúc Master List 186714\nCác trường được map theo 5 nhóm từ form `FizaMLHUB Form`:\n- **Nhóm 1 – Định danh & Kết nối:** fullname · email · phone · fiza_id\n- **Nhóm 2 – Hoạt động kinh doanh:** business_name · industry · district · address\n- **Nhóm 3 – Tài chính & Đối soát:** package_id · subscription_status · payment_method · registration_date · expiry_date\n- **Nhóm 4 – Chăm sóc & Chấm điểm:** pic · lead_score · support_note · onboarding_step *(nội bộ CSKH)*\n- **Nhóm 5 – Liên kết bên ngoài:** website · facebook · tiktok · maps",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "item": [
    {
      "name": "Health Check",
      "request": {
        "method": "GET",
        "header": [],
        "url": {
          "raw": "{{base_url}}/health",
          "host": ["{{base_url}}"],
          "path": ["health"]
        },
        "description": "Kiểm tra trạng thái hoạt động của server. Không yêu cầu xác thực.\n\nDùng để:\n- Kiểm tra server đã khởi động chưa\n- Ping từ load balancer / uptime monitor"
      },
      "response": [
        {
          "name": "200 OK — Server hoạt động bình thường",
          "originalRequest": {
            "method": "GET",
            "header": [],
            "url": { "raw": "{{base_url}}/health", "host": ["{{base_url}}"], "path": ["health"] }
          },
          "status": "OK",
          "code": 200,
          "header": [{ "key": "Content-Type", "value": "application/json" }],
          "body": "{\n  \"status\": \"ok\",\n  \"timestamp\": \"2026-04-15T10:00:00.000Z\"\n}"
        }
      ]
    },
    {
      "name": "Khởi tạo Tài khoản (Onboard) — Full Fields",
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "x-api-key",
            "value": "{{api_key}}",
            "type": "text",
            "description": "API Key được MLHUB cấp riêng cho đối tác. Lưu trong Postman Environment, không hardcode vào collection."
          },
          {
            "key": "Content-Type",
            "value": "application/json",
            "type": "text"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"fiza_id\": \"FZ-0071\",\n  \"email\": \"vankhoa.lqd+k071@gmail.com\",\n  \"contact_name\": \"Nguyễn Văn K071\",\n  \"phone\": \"0609121271\",\n\n  \"business_name\": \"Quán Cơm Nhà Bé K071\",\n  \"industry\": \"sop03\",\n  \"district\": \"Quận Hải Châu\",\n  \"address\": \"123 Nguyễn Văn Linh, Đà Nẵng\",\n\n  \"package_id\": \"coban\",\n  \"payment_method\": \"GTELPAY\",\n  \"business_password\": \"Demo@Pass123!\",\n\n  \"website\": \"https://restaurant.app\",\n  \"facebook\": \"https://fb.com/restaurant\",\n  \"tiktok\": \"https://tiktok.com/@restaurant\",\n  \"maps\": \"https://maps.app.goo.gl/123\"\n}",
          "options": { "raw": { "language": "json" } }
        },
        "url": {
          "raw": "{{base_url}}/api/v1/onboard",
          "host": ["{{base_url}}"],
          "path": ["api", "v1", "onboard"]
        },
        "description": "Endpoint **một chạm** — tạo Sub-account mới trên MLHUB Engine và đồng bộ toàn bộ thông tin hồ sơ vào Master Contact List (List ID: `186714`) chỉ trong một lần gọi.\n\n---\n\n## Trường bắt buộc\n| Trường | MLHUB Field ID | Mô tả |\n|---|---|---|\n| `fiza_id` | `499281` | Mã định danh khách hàng trên FizaHub (VD: `FZ-0071`) |\n| `email` | `499283` | Email, khóa chính tạo Sub-account |\n\n## Nhóm 1 — Định danh & Kết nối\n| Trường | MLHUB Field ID | Mô tả |\n|---|---|---|\n| `contact_name` | `499280` | Họ & Tên người đại diện |\n| `phone` | `499284` | Số điện thoại |\n\n## Nhóm 2 — Hoạt động kinh doanh\n| Trường | MLHUB Field ID | Mô tả |\n|---|---|---|\n| `business_name` | `499304` | Tên cửa hàng / hộ kinh doanh |\n| `industry` | `499292` | Alias ngành: `sop01`–`sop06` (tự map sang tiếng Việt) |\n| `district` | `1000067` | Quận / Huyện |\n| `address` | `499286` | Địa chỉ chi tiết |\n\n## Nhóm 3 — Tài chính & Gói dịch vụ\n| Trường | MLHUB Field ID | Mô tả |\n|---|---|---|\n| `package_id` | `1168449` | Alias gói: `coban` · `caocap` · `tuychon` |\n| `payment_method` | `1168988` | Hình thức thanh toán (VD: `GTELPAY`) |\n| `business_password` | *(Engine only)* | Mật khẩu đăng nhập MLHUB. Tự sinh 8 ký tự nếu bỏ trống |\n\n> `subscription_status`, `registration_date`, `expiry_date` do hệ thống tự động điền.\n\n## Nhóm 5 — Liên kết bên ngoài\n| Trường | MLHUB Field ID | Mô tả |\n|---|---|---|\n| `website` | `499293` | URL trang web |\n| `facebook` | `499299` | URL Fanpage Facebook |\n| `tiktok` | `1169778` | URL kênh TikTok |\n| `maps` | `499303` | URL Google Maps |\n\n> **Nhóm 4 (pic · lead_score · support_note · onboarding_step)** là các trường nội bộ do CSKH cập nhật thủ công trên MLHUB — không truyền từ endpoint này."
      },
      "response": [
        {
          "name": "200 OK — Tạo tài khoản và sync thành công",
          "originalRequest": {
            "method": "POST",
            "header": [
              { "key": "x-api-key", "value": "{{api_key}}", "type": "text" },
              { "key": "Content-Type", "value": "application/json", "type": "text" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"fiza_id\": \"FZ-0071\",\n  \"email\": \"vankhoa.lqd+k071@gmail.com\",\n  \"contact_name\": \"Nguyễn Văn K071\",\n  \"phone\": \"0609121271\",\n  \"business_name\": \"Quán Cơm Nhà Bé K071\",\n  \"industry\": \"sop03\",\n  \"district\": \"Quận Hải Châu\",\n  \"address\": \"123 Nguyễn Văn Linh, Đà Nẵng\",\n  \"package_id\": \"coban\",\n  \"payment_method\": \"GTELPAY\",\n  \"business_password\": \"Demo@Pass123!\",\n  \"website\": \"https://restaurant.app\",\n  \"facebook\": \"https://fb.com/restaurant\",\n  \"tiktok\": \"https://tiktok.com/@restaurant\",\n  \"maps\": \"https://maps.app.goo.gl/123\"\n}"
            },
            "url": { "raw": "{{base_url}}/api/v1/onboard", "host": ["{{base_url}}"], "path": ["api", "v1", "onboard"] }
          },
          "status": "OK",
          "code": 200,
          "header": [{ "key": "Content-Type", "value": "application/json" }],
          "body": "{\n  \"success\": true,\n  \"message\": \"Account created and contact synced successfully.\",\n  \"data\": {\n    \"mlhub_account_id\": \"98765\",\n    \"email\": \"vankhoa.lqd+k071@gmail.com\"\n  }\n}"
        },
        {
          "name": "207 Multi-Status — Tài khoản tạo OK, sync Master List thất bại",
          "originalRequest": {
            "method": "POST",
            "header": [
              { "key": "x-api-key", "value": "{{api_key}}", "type": "text" },
              { "key": "Content-Type", "value": "application/json", "type": "text" }
            ],
            "body": { "mode": "raw", "raw": "{\n  \"fiza_id\": \"FZ-0071\",\n  \"email\": \"vankhoa.lqd+k071@gmail.com\"\n}" },
            "url": { "raw": "{{base_url}}/api/v1/onboard", "host": ["{{base_url}}"], "path": ["api", "v1", "onboard"] }
          },
          "status": "Multi-Status",
          "code": 207,
          "header": [{ "key": "Content-Type", "value": "application/json" }],
          "body": "{\n  \"success\": true,\n  \"warning\": \"Account created but contact sync to master list failed. Please retry the sync.\",\n  \"data\": {\n    \"mlhub_account_id\": \"98765\",\n    \"email\": \"vankhoa.lqd+k071@gmail.com\"\n  }\n}"
        },
        {
          "name": "400 Bad Request — Validation thất bại",
          "originalRequest": {
            "method": "POST",
            "header": [
              { "key": "x-api-key", "value": "{{api_key}}", "type": "text" },
              { "key": "Content-Type", "value": "application/json", "type": "text" }
            ],
            "body": { "mode": "raw", "raw": "{\n  \"business_name\": \"Thiếu fiza_id và email\"\n}" },
            "url": { "raw": "{{base_url}}/api/v1/onboard", "host": ["{{base_url}}"], "path": ["api", "v1", "onboard"] }
          },
          "status": "Bad Request",
          "code": 400,
          "header": [{ "key": "Content-Type", "value": "application/json" }],
          "body": "{\n  \"success\": false,\n  \"error\": \"Validation failed\",\n  \"details\": [\n    \"\\\"fiza_id\\\" là bắt buộc\",\n    \"\\\"email\\\" là bắt buộc\"\n  ]\n}"
        },
        {
          "name": "401 Unauthorized — API Key sai hoặc thiếu",
          "originalRequest": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json", "type": "text" }],
            "body": { "mode": "raw", "raw": "{\n  \"fiza_id\": \"FZ-0071\",\n  \"email\": \"test@example.com\"\n}" },
            "url": { "raw": "{{base_url}}/api/v1/onboard", "host": ["{{base_url}}"], "path": ["api", "v1", "onboard"] }
          },
          "status": "Unauthorized",
          "code": 401,
          "header": [{ "key": "Content-Type", "value": "application/json" }],
          "body": "{\n  \"success\": false,\n  \"error\": \"Unauthorized: Invalid or missing API Key\"\n}"
        },
        {
          "name": "429 Too Many Requests — Vượt rate limit",
          "status": "Too Many Requests",
          "code": 429,
          "header": [
            { "key": "Content-Type", "value": "application/json" },
            { "key": "RateLimit-Limit", "value": "30" },
            { "key": "RateLimit-Remaining", "value": "0" },
            { "key": "RateLimit-Reset", "value": "900" }
          ],
          "body": "{\n  \"success\": false,\n  \"error\": \"Too many requests. Please try again after 15 minutes.\"\n}"
        },
        {
          "name": "502 Bad Gateway — Engine không trả về account ID",
          "status": "Bad Gateway",
          "code": 502,
          "header": [{ "key": "Content-Type", "value": "application/json" }],
          "body": "{\n  \"success\": false,\n  \"error\": \"Account may have been created on the engine but no account ID was returned. Please verify manually and retry.\",\n  \"code\": \"ENGINE_ID_NOT_RETURNED\"\n}"
        },
        {
          "name": "502 Bad Gateway — Engine từ chối tạo tài khoản",
          "status": "Bad Gateway",
          "code": 502,
          "header": [{ "key": "Content-Type", "value": "application/json" }],
          "body": "{\n  \"success\": false,\n  \"error\": \"Failed to create account on the engine. Please try again later.\",\n  \"code\": \"ENGINE_CREATE_FAILED\"\n}"
        }
      ]
    },
    {
      "name": "Khởi tạo Tài khoản — Chỉ trường bắt buộc (Minimal)",
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "x-api-key",
            "value": "{{api_key}}",
            "type": "text"
          },
          {
            "key": "Content-Type",
            "value": "application/json",
            "type": "text"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"fiza_id\": \"FZ-0072\",\n  \"email\": \"vankhoa.lqd+k072@gmail.com\"\n}",
          "options": { "raw": { "language": "json" } }
        },
        "url": {
          "raw": "{{base_url}}/api/v1/onboard",
          "host": ["{{base_url}}"],
          "path": ["api", "v1", "onboard"]
        },
        "description": "Test với tối thiểu 2 trường bắt buộc — hệ thống sẽ tự động điền `subscription_status = ACTIVE`, `registration_date`, `expiry_date` và sinh mật khẩu ngẫu nhiên."
      },
      "response": []
    },
    {
      "name": "Test 401 — Không có API Key",
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json",
            "type": "text"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"fiza_id\": \"FZ-0099\",\n  \"email\": \"test.unauth@example.com\"\n}",
          "options": { "raw": { "language": "json" } }
        },
        "url": {
          "raw": "{{base_url}}/api/v1/onboard",
          "host": ["{{base_url}}"],
          "path": ["api", "v1", "onboard"]
        },
        "description": "Test trường hợp gọi API không có header `x-api-key` — phải nhận 401 Unauthorized."
      },
      "response": []
    },
    {
      "name": "Test 400 — Thiếu trường bắt buộc",
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "x-api-key",
            "value": "{{api_key}}",
            "type": "text"
          },
          {
            "key": "Content-Type",
            "value": "application/json",
            "type": "text"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"business_name\": \"Thiếu fiza_id và email\"\n}",
          "options": { "raw": { "language": "json" } }
        },
        "url": {
          "raw": "{{base_url}}/api/v1/onboard",
          "host": ["{{base_url}}"],
          "path": ["api", "v1", "onboard"]
        },
        "description": "Test trường hợp thiếu `fiza_id` và `email` — phải nhận 400 Validation failed."
      },
      "response": []
    }
  ],
  "variable": [
    {
      "key": "base_url",
      "value": "http://localhost:3000",
      "type": "string",
      "description": "Base URL của server. Đổi thành https://api-sandbox.mlhub.vn khi deploy production."
    },
    {
      "key": "api_key",
      "value": "FizaHub@2026",
      "type": "string",
      "description": "API Key local dev — lấy từ FIZAHUB_SECRET_KEY trong .env. Đổi thành key production khi deploy."
    }
  ]
}
