Trên trang này
- Tổng quan
- Mua & xác minh tên miền
- Trỏ DNS & HTTPS
- Máy chủ gốc (backend)
- Trạng thái đơn
- Gia hạn & tạm ngưng
- Log tấn công & thống kê
- Luật riêng
- Nhịp thao tác
- Mã lỗi riêng
- GET /waf/products
- GET /waf/price
- POST /waf/verify-domain
- POST /waf/quote
- POST /waf/buy
- GET /waf/list
- GET /waf/info
- POST /waf/renew
- POST /waf/auto-renew
- POST /waf/change-cycle
- POST /waf/set-backend
- POST /waf/delete
- GET /waf/logs
- GET /waf/stats
Tổng quan
Địa chỉ gốc của các endpoint trên trang này:
https://cloudmoon.net/api/v1| Endpoint | Việc | Quyền khoá |
|---|---|---|
GET /waf/products |
Danh mục WAF: một sản phẩm (WAF cho một tên miền) — không còn chu kỳ nào đang bán thì danh sách rỗng. in_stock = còn ch… | Chỉ đọc |
GET /waf/price |
Bảng giá theo chu kỳ (khuôn cũ của web con — danh mục đầy đủ ở /waf/products): cycles[chu kỳ] = months · amount (đã trừ… | Chỉ đọc |
POST /waf/verify-domain |
Xác minh bạn quản lý tên miền để MUA WAF cho nó (bắt buộc với mua mới). Tên miền mua tại đây đang chạy trong tài khoản,… | Toàn quyền |
POST /waf/quote |
BÁO GIÁ — không trừ tiền, không ghi gì, khoá chỉ đọc gọi được. type buy (mặc định): CÙNG thân và CÙNG bộ kiểm với /waf/… | Chỉ đọc |
POST /waf/buy |
Mua WAF cho MỘT tên miền — trừ tiền và dựng cấu hình bảo vệ NGAY trong lượt gọi: HTTP 200 provision_status = ready (trỏ… | Toàn quyền |
GET /waf/list |
Mọi WAF của tài khoản: provision_status (ready · provisioning — đang hoàn tất cấu hình · suspended — tạm ngưng vì quá h… | Chỉ đọc |
GET /waf/info |
Chi tiết một WAF: mọi trường của /waf/list + renew_until (hạn mới nếu gia hạn ngay — dự tính, chưa xét lượt gia hạn tro… | Chỉ đọc |
POST /waf/renew |
Gia hạn một WAF thêm MỘT chu kỳ (chu kỳ ghi trên đơn) — trừ ví NGAY (báo giá: /waf/quote type renew). amount = giá ghi … | Toàn quyền |
POST /waf/auto-renew |
ĐẶT tự gia hạn (không lật — gửi lại cùng giá trị vẫn thành công, sau nhịp 5 giây). Bật ⇒ mỗi giờ, từ lúc còn ≤ 7 ngày t… | Toàn quyền |
POST /waf/change-cycle |
Đổi chu kỳ cho LẦN GIA HẠN SAU — không trừ tiền, không đổi hạn (amount 0): price_buy = giá chu kỳ mới hiện hành, đã trừ… | Toàn quyền |
POST /waf/set-backend |
Đổi máy chủ gốc mà WAF chuyển truy cập sạch về: http(s):// + IP công khai hoặc tên miền (phân giải IPv4 lúc lưu, lưu th… | Toàn quyền |
POST /waf/delete |
XOÁ một WAF — KHÔNG hoàn tiền, không khôi phục được (confirm = order_code): đơn chuyển expired ngay, cấu hình bảo vệ đư… | Toàn quyền |
GET /waf/logs |
Log tấn công đã ghi nhận (mới nhất trước) của tài khoản — ?order_code= chỉ lấy log của tên miền hiện tại của đơn ấy (đơ… | Chỉ đọc |
GET /waf/stats |
Lưu lượng HÔM NAY (từ 0 giờ, giờ Việt Nam) của một WAF: total_requests · blocked · passed · top_ips (tối đa 5 IP bị chặ… | Chỉ đọc |
Giá đại lý: Danh mục, báo giá và lệnh mua trả về (và trừ ví) giá đã trừ chiết khấu theo cấp đại lý; gia hạn theo GIÁ GHI TRÊN ĐƠN (giá lúc mua — đã trừ chiết khấu khi ấy); đổi chu kỳ ghi giá chu kỳ mới đã trừ chiết khấu như lúc mua cho lần gia hạn kế. — xem mục Tài khoản đại lý.
Mua & xác minh tên miền
Mỗi đơn WAF bảo vệ đúng một tên miền — tên miền gốc hoặc một tên miền con, không nhận wildcard (bảo vệ cả www. thì mua thêm một đơn cho tên ấy). Lệnh mua kiểm hết, trừ ví và dựng cấu hình bảo vệ ngay trong lượt gọi; bạn chỉ còn trỏ bản ghi A (mục Trỏ DNS & HTTPS).
POST /waf/verify-domainvới{domain}(khoá Toàn quyền — cấp mã là một lệnh ghi): mua mới cần bằng chứng bạn quản lý tên miền. Đã có ⇒verified: truengay,proof=registered_here(đúng tên miền ấy mua tại đây, đang chạy và còn hạn trong tài khoản — tên miền mẹ không tính cho tên miền con) hoặctxt(đã xác minh TXT trong 7 ngày). Chưa có ⇒record: bản ghi TXT tên_waf-verify.<tên miền>, giá trị là mã 32 ký tự riêng cho cặp tài khoản + tên miền (gọi lại vẫn ra đúng mã ấy).- Thêm bản ghi TXT tại nơi quản lý DNS của tên miền, rồi gọi lại kèm
check: true⇒verified: true(kiểm đạt dùng được cho lệnh mua trong 7 ngày), hoặcverified: false+result:not_found(chưa thấy TXT đúng tên) ·wrong_value(có TXT đúng tên nhưng không giá trị nào khớp mã — dán đúng mã, không thêm dấu nháy hay khoảng trắng) ·cname(tên ấy là một CNAME — bản ghi phải là TXT đặt trực tiếp đúng tên). Lượt vừa cấp mã chưa tra DNS (checked: false). GET /waf/products:cycles(chu kỳ đang bán, ngắn → dài) ·pricing[chu kỳ]=amount(số sẽ trừ — đã trừ chiết khấu đại lý) ·amount_original·months·per_month·in_stock(còn chỗ trên máy chủ bảo vệ).POST /waf/quotevới cùng thân lệnh mua (khoá Chỉ đọc gọi được) chạy đúng bộ kiểm của lệnh mua rồi trảamount,time_expiredự kiến vàenough— không trừ tiền, không giữ chỗ hay giữ giá.POST /waf/buyvới{domain, backend_upstream, billing_cycle?, name?}và headerIdempotency-Key⇒ HTTP 200,provision_status: "ready",charged: true,order_codevàdns— bản ghi A cần trỏ.
- HTTP 202
provision_status: "provisioning"+charged: true: tiền đã trừ, đơn đã có, nhưng máy chủ bảo vệ chưa xác nhận xong cấu hình — đừng mua lại; hệ thống tự hoàn tất (thử lại mỗi vài phút). Hỏiinfothưa thôi tớiready. Hạn của đơn tính từ lúc mua, kể cả khi cònprovisioning. - Lời chối ở bước kiểm chưa trừ đồng nào:
409 DOMAIN_NOT_VERIFIED(chưa có bằng chứng —data.record= bản ghi TXT đã cấp,nullnếu chưa cấp mã: gọiverify-domain) ·409 DOMAIN_IN_USE(tên miền đang được một WAF khác bảo vệ, hoặc cấu hình cũ của nó chưa gỡ xong — chỉ báo khi bạn đã có bằng chứng quyền tên miền) ·409 OUT_OF_STOCK(hết chỗ) ·409 PRICE_CHANGED(giá vừa tăng giữa lúc kiểm và lúc trừ —data.price_buy= số mới; báo giá lại rồi gửi lệnh mới vớiIdempotency-Keymới) ·402(thiếu tiền) ·400(tên miền, backend, chu kỳ hoặc tên không hợp lệ — sửa theomsg). - Ngoại lệ:
400 FAILEDở lệnh mua có thể là giao dịch chưa rõ kết quả — đừng mua lại ngay: đối chiếuGET /waf/listhoặc liên hệ hỗ trợ; gửi lại cùngIdempotency-Keynhận lại đúng lỗi ấy. domainđược chuẩn hoá trước khi kiểm: chữ thường; bỏhttp(s)://, đường dẫn, cổng và dấu chấm cuối; tên miền quốc tế chuyển sang punycode. Tối đa 253 ký tự (xác minh TXT cần thêm chỗ cho_waf-verify.⇒ tối đa 241).name— tên gợi nhớ, tối đa 200 ký tự (dài hơn bị chối, không bị cắt), bỏ trống = tên miền.billing_cyclebỏ trống =onemonth.- Đơn mới bật sẵn tự gia hạn (
billing.renew_auto: "on") — chỉ muốn một kỳ thì gọiPOST /waf/auto-renewvớienabled: false. Ngày mua đã tính là lượt gia hạn của ngày ấy: gia hạn được từ 0 giờ hôm sau. - Xác minh: mỗi tên miền cách nhau tối thiểu 10 giây giữa hai lần kiểm (
429 COOLDOWN) · tối đa 30 lần kiểm / giờ và 30 tên miền mới / 24 giờ cho mỗi tài khoản (429 RATE_LIMITED) · tra DNS hỏng ⇒503 UNAVAILABLE(thử lại). Đừng gửicheck: truetrước khi thêm bản ghi: hệ thống DNS có thể nhớ "chưa có" một thời gian (tới vài phút hoặc lâu hơn, tuỳ cấu hình DNS của tên miền).verify-domainkhông cho biết tên miền có đang được bảo vệ hay không.
Trỏ DNS & HTTPS
- Đơn
ready⇒ tạo bản ghi A cho đúng tên miền của đơn, trỏ vềdns.value(=server_ipởlist/info) — địa chỉ IP máy chủ bảo vệ của đơn, không phải IP máy chủ gốc. Lệnh mua không tự sửa DNS: tới khi bản ghi mới có hiệu lực (thường 5–30 phút, tuỳ TTL), truy cập vẫn đi thẳng tới máy chủ gốc. - Truy cập vào tên miền ⇒ qua máy chủ bảo vệ ⇒ lọc tấn công ⇒ chuyển phần sạch về
backend_upstream. - HTTPS — tuỳ cách trỏ DNS:
- Qua proxy Cloudflare (đám mây cam) + chế độ SSL/TLS "Flexible" — cách khuyên dùng: có HTTPS ngay, không cần chứng chỉ trên WAF — Cloudflare cấp HTTPS cho người truy cập, chặng Cloudflare → máy chủ bảo vệ đi qua cổng 80. Chế độ "Full" / "Full (strict)" ⇒ Cloudflare báo lỗi 525. Khi bật proxy, máy chủ bảo vệ chỉ thấy IP của Cloudflare:
src_ipởlogsvàtop_ipsởstatslà IP Cloudflare (đổi theo từng lượt), không phải IP người truy cập. - Trỏ bản ghi A thẳng (tắt proxy — đám mây xám — hoặc DNS khác):
src_ip/top_ipslà IP thật của người truy cập, nhưng hiện chỉ có HTTP (cổng 80). API không cấp chứng chỉ.
- Qua proxy Cloudflare (đám mây cam) + chế độ SSL/TLS "Flexible" — cách khuyên dùng: có HTTPS ngay, không cần chứng chỉ trên WAF — Cloudflare cấp HTTPS cho người truy cập, chặng Cloudflare → máy chủ bảo vệ đi qua cổng 80. Chế độ "Full" / "Full (strict)" ⇒ Cloudflare báo lỗi 525. Khi bật proxy, máy chủ bảo vệ chỉ thấy IP của Cloudflare:
- Ẩn IP gốc thật sự: cấu hình tường lửa của máy chủ gốc chỉ cho phép IP máy chủ bảo vệ (
server_ip) vào cổng web. Ai còn biết IP gốc thì vẫn đánh thẳng được, vòng qua WAF.
Máy chủ gốc (backend)
backend_upstream= địa chỉ máy chủ thật của website:http://hoặchttps://+ IP công khai hoặc tên miền + cổng (bỏ trống cổng = 80 vớihttp· 443 vớihttps; bỏ trống scheme =http). Đường dẫn / query không được giữ — hệ thống lưu dạngscheme://IP:cổng.- Tên miền được phân giải (IPv4) lúc lưu và lưu thành IP — máy chủ gốc đổi IP thì gọi
set-backendlại. IPv6 chưa hỗ trợ. - Bị chối (
400 BAD_REQUEST): địa chỉ nội bộ, loopback, các dải đặc biệt / không công khai, địa chỉ hạ tầng của hệ thống, tên miền không phân giải được. Ngoại lệ: website đặt trên hosting tại đây dùng làm backend được (cổng 80 / 443). Hệ thống tạm không kiểm được địa chỉ ⇒503 UNAVAILABLE(chưa đổi gì — thử lại). POST /waf/set-backendvới{order_code, backend_upstream}: lưu rồi áp ngay —applied: true= máy chủ bảo vệ đã nhận;false= đã lưu, hệ thống áp tiếp ở nền (vài phút). Gửi lại đúng backend đang dùng = áp lại cấu hình (tự chữa khi cấu hình lệch).- Đơn tạm ngưng ⇒
409 RENEW_REQUIRED(gia hạn trước) · đơn mua xong mà cấu hình bảo vệ chưa dựng xong (lệnh mua trả 202) ⇒409 PROVISIONING· đơn hết hạn / đã xoá ⇒409 ORDER_EXPIRED.
Trạng thái đơn
list / info có provision_status (cùng order_status):
provision_status | Nghĩa (kèm order_status) |
|---|---|
ready | active — cấu hình bảo vệ đã dựng xong: trỏ bản ghi A là WAF lọc ngay; làm được mọi lệnh. |
provisioning | active — đã trừ tiền, cấu hình bảo vệ đang được dựng / áp, hệ thống tự hoàn tất. Chưa có cấu hình thì chưa đổi backend được (409 PROVISIONING). |
suspended | pending_expired — tạm ngưng vì quá hạn: truy cập qua WAF bị chặn, không tới máy chủ gốc (lệnh chặn áp ngay khi đơn chuyển trạng thái — gặp lỗi tạm thời thì hệ thống tự áp lại sau ít phút); cấu hình, IP và tên miền giữ nguyên. Gia hạn trước renew_deadline để mở lại. |
expired | expired — hết hạn hẳn, hoặc đã xoá: cấu hình bảo vệ đã / đang được gỡ, tên miền đã nhả, không lệnh ghi nào làm được nữa. info vẫn đọc được cho tới khi đơn bị xoá hẳn (30 ngày sau time_expire); stats báo available: false; log cũ của đơn đọc qua /waf/logs không lọc order_code. |
allowed_actions(ở cảlistlẫninfo) — lệnh GHI làm được ngay lúc này, cùng luật với các nút trên trang quản lý WAF:renew·auto_renew·change_cycle·set_backend·delete. Tên nào vắng mặt thì lệnh ấy đang bị chối: đơn tạm ngưng không cóset_backend; từrenew_deadlinemấtrenew+auto_renew; đơn đang rao bán trên chợ mấtchange_cycle+delete; đơnexpiredrỗng. Chỉ xét trạng thái đơn — không tính nhịp (mục Nhịp thao tác), lượt gia hạn trong ngày hay số dư.dns{type: "A",name,value} — bản ghi cần trỏ;nullkhi đơn đã hết hạn / đã xoá.billing:price_buy(giá ghi trên đơn) ·price_renew(số lần gia hạn kế sẽ trừ —nullkhi trạng thái đơn không cho gia hạn; đã gia hạn hôm nay hay thiếu tiền không làm nónull) ·billing_cycle·months·renew_auto·time_buy·time_expire.infothêmrenew_until(hạn mới nếu gia hạn ngay — dự tính) vàrenew_deadline(hạn chót gia hạn =time_expire+ 7 ngày).listtrả mọi đơn đang thuộc tài khoản — mua trên web lẫn qua API, nhận chuyển quyền — kể cả đơn đã hết hạn / đã xoá cho tới khi bị xoá hẳn; lọc bằng?status=active·pending_expired·expired.
Gia hạn & tạm ngưng
POST /waf/renewvới{order_code}gia hạn một chu kỳ (chu kỳ ghi trên đơn) và trừ ví ngay:amount=billing.price_renew— giá ghi trên đơn (giá lúc mua, đã trừ chiết khấu khi ấy; đổi chu kỳ thì là giá chu kỳ mới). Hạn mới = max(bây giờ, hạn cũ) + số tháng của chu kỳ (tháng lịch: onemonth = 1 · sixmonth = 6 · oneyear = 12 · twoyear = 24 · threeyear = 36). Báo giá:quotevới{"type": "renew", "order_code": "…"}.- Mỗi đơn một lượt gia hạn mỗi ngày, tính cả ngày mua, gia hạn trên web và tự gia hạn ⇒
429 COOLDOWN,Retry-Aftertới 0 giờ. Giá ghi trên đơn vừa tăng hoặc chu kỳ vừa đổi giữa lúc kiểm và lúc trừ (một lệnh đổi chu kỳ chen giữa) ⇒409 PRICE_CHANGED(data.price_buy·data.billing_cycle), chưa trừ tiền. Chu kỳ thôi bán không chặn gia hạn đơn đang có. - Đổi chu kỳ (
POST /waf/change-cycle,{order_code, billing_cycle}): áp cho lần gia hạn kế — không trừ tiền, không đổi hạn hiện tại (amount: 0);price_buy= giá chu kỳ mới hiện hành, đã trừ chiết khấu đại lý của tài khoản. Cùng chu kỳ đang dùng ⇒ thành công, không đổi gì (changed: false) · chu kỳ không đang bán ⇒400· đơn đang rao bán trên chợ ⇒409 LISTED_ON_MARKETPLACE· đơn hết hạn ⇒409 ORDER_EXPIRED. - Tự gia hạn (
billing.renew_auto— đơn mới bật sẵn; đặt bằngPOST /waf/auto-renewvớienabledlà boolean — lệnh ĐẶT giá trị, gửi lại cùng giá trị không lật ngược): mỗi giờ, từ lúc còn 7 ngày hoặc ít hơn tớitime_expire— kể cả khi đơn đã tạm ngưng, cho tới hạn chót — hệ thống thử gia hạn một chu kỳ, giữ chu kỳ và giá ghi trên đơn; số dư thiếu ⇒ bỏ lượt, thử lại giờ sau. - Hết hạn: qua
time_expiremà chưa gia hạn ⇒ ở lượt kiểm kế tiếp (mỗi 6 giờ) đơn chuyểnpending_expired(suspended): truy cập qua WAF bị chặn (lỗi tạm thời khi áp lệnh chặn ⇒ hệ thống tự áp lại sau ít phút), cấu hình + IP + tên miền giữ nguyên. Gia hạn trướcrenew_deadline(7 ngày sau hạn) ⇒ đơn hoạt động lại và truy cập được mở lại —reopened: true(đã mở) ·false(đã gia hạn, đang mở lại ở nền);null= đơn không bị tạm ngưng. - Từ
renew_deadlinekhông gia hạn được nữa (409 ORDER_EXPIRED) — ở lượt kiểm sau đó đơn chuyểnexpired: cấu hình bảo vệ bị gỡ, tên miền được nhả (mua WAF mới cho nó được khi gỡ xong). Đơnexpiredbị xoá hẳn khỏilist30 ngày sautime_expire.
Log tấn công & thống kê
GET /waf/logs— sự kiện tấn công đã ghi nhận, mới nhất trước:host·src_ip(IP nguồn — tên miền bật proxy Cloudflare thì là IP của Cloudflare, mục Trỏ DNS & HTTPS) ·attack_type(sqli·xss·rce·ssrf·xxe·ssti·file_inclusion·path_traversal·deserialization·backdoor·scanner·file_upload·other) ·action(1= đã chặn, cùng nghĩa vớiblocked: true) ·url_path(tối đa 500 ký tự) ·risk_level(1thấp ·2trung bình ·3cao;0= chưa xếp mức) ·event_time+time(ISO 8601). Không lưu header, thân hay payload của lượt truy cập.- Không truyền
order_code⇒ mọi log của tài khoản; cóorder_code⇒ log của tên miền hiện tại của đơn ấy (đơn đã hết hạn / đã xoá không còn tên miền ⇒ danh sách rỗng — log cũ vẫn có trong danh sách toàn tài khoản). Phân tranglimit(1–200, mặc định 50) +page. - Log về theo nhịp kéo từ máy chủ bảo vệ (khoảng 5 phút, có thể lâu hơn lúc tải cao) và được giữ 30 ngày. Mỗi sự kiện gán cho đơn đang giữ tên miền lúc ghi nhận: mua lại một tên miền bằng đơn mới không thấy log đời trước của tài khoản khác; chuyển quyền thì log đã có đi theo đơn sang người nhận.
GET /waf/stats?order_code=…— lưu lượng hôm nay (từ 0 giờ, giờ Việt Nam) của đúng tên miền:total_requests·blocked·passed(= tổng − chặn) ·top_ips(tối đa 5 IP bị chặn nhiều nhất hôm nay ⇒ số lượt — luôn là object; sau proxy Cloudflare là IP Cloudflare) ·synced_at(lúc lấy số) ·stale(true= đang trả số cũ hơn 60 giây). Số làm mới tối đa mỗi 60 giây; lượt truy cập mới hiện vào số sau khoảng 1–2 phút.- Chưa lấy được số ⇒
available: falsevà ba số lànull— không có nghĩa là không có truy cập.top_ipslấy từ log đã kéo nên có thể lệch ba số kia vài phút.
Luật riêng
- Phạm vi bảo vệ: WAF bảo vệ tầng ứng dụng (L7) — lọc SQLi / XSS / RCE / quét lỗ hổng — và ẩn IP máy chủ gốc. KHÔNG chống tấn công DDoS băng thông lớn (L3/L4): loại đó cần hạ tầng lọc chuyên dụng.
- Xoá (
POST /waf/delete,confirm= đúngorder_code): đơn chuyểnexpiredngay, cấu hình bảo vệ được gỡ (có thể hoàn tất sau ít phút) — không hoàn tiền, không khôi phục được. Đơn đang rao bán trên chợ ⇒409 LISTED_ON_MARKETPLACE· đã hết hạn / đã xoá ⇒409 ORDER_EXPIRED. - Dịch vụ WAF tạm dừng bán:
products·price·verify-domain· báo giá mua mới · lệnh mua nhận503 SERVICE_DISABLED(GET /services/statusbáowaf: false); mọi lệnh trên đơn đang có vẫn chạy bình thường. - Hết chỗ:
productsvẫn bày sản phẩm vớiin_stock: false(?in_stock=1⇒ danh sách rỗng) — báo giá / lệnh mua ⇒409 OUT_OF_STOCK; trang mua trên web cùng lúc bày băng "tạm hết chỗ" và khoá nút mua. Đơn đang có không bị ảnh hưởng. - Giới hạn lệnh mua (mỗi tài khoản): tối đa 10 lượt mua WAF mỗi giờ — đếm cả lượt mua trên web (
429 RATE_LIMITED), tính riêng với các sản phẩm khác. Số dư xét lệnh mua là số dư khả dụng — đã trừ tiền các lệnh mua Cloud VPS còn chờ tạo máy. - Không làm qua API: chuyển đơn sang tài khoản khác (xác nhận qua email trên web) · rao bán trên chợ · chuyển sang máy chủ bảo vệ khác — dùng trang quản lý WAF trên web hoặc liên hệ hỗ trợ.
- Chạy thử (
X-Sandbox: 1): lệnh mua trả mãSANDBOX…(21 ký tự) — đơn mẫu tên miềnsandbox-….example, IP máy chủ bảo vệ + backend thuộc dải tài liệu203.0.113.0/24, chu kỳ lấy từ mã, giá dựng lại từ bảng giá hiện hành mỗi lần hỏi.X-Sandbox-Scenario: PROVISION_FAILED⇒ 202provisioning;infocủa mã ấy vềreadysau khoảng 60 giây. Gia hạn đơn mẫu vừa tạo ⇒429 COOLDOWNnhư thật (mua xong không gia hạn trong ngày) ·logsmẫu rỗng ·statsmẫu là số giả.verify-domainchạy thử không cấp mã mới, không tra DNS. Vớiorder_codethật,statschạy thử chỉ đọc số đã lưu, không hỏi máy chủ bảo vệ. Không lưu gì: mã không có tronglist.
Nhịp thao tác trên cùng một WAF
Các lệnh trên cùng một WAF phải cách lệnh trước một khoảng tối thiểu — nhịp này chỉ áp cho lệnh gửi qua API, để chặn lệnh gửi lặp. Các việc trong cùng một dòng dùng chung một đồng hồ. Gửi sớm hơn ⇒ 429 COOLDOWN (header Retry-After cho biết còn bao nhiêu giây); gửi trong lúc máy đang xử lý lệnh khác ⇒ 429 IN_PROGRESS.
| Lệnh | Cách lệnh trước trên cùng WAF |
|---|---|
| Gia hạn | 1 phút (tính riêng) |
| Đổi backend | 1 phút (tính riêng) |
| Bật/tắt tự gia hạn | 5 giây (tính riêng) |
| Gia hạn | tối đa 1 lượt / ngày / đơn (tính cả ngày mua, gia hạn trên web và tự gia hạn — lượt thứ hai ⇒ 429 COOLDOWN, Retry-After tới 0 giờ) |
| Đổi chu kỳ · xoá | không phải chờ (chỉ một lệnh mỗi lúc trên cùng đơn (429 IN_PROGRESS)) |
Mã lỗi riêng
Ngoài các mã lỗi chung của mọi endpoint, trang này còn có các mã dưới đây. Hãy rẽ nhánh theo code.
| HTTP | code | Ý nghĩa | Nên làm gì |
|---|---|---|---|
| 409 | LISTED_ON_MARKETPLACE |
WAF đang được rao bán trên chợ — xoá và đổi chu kỳ bị chặn. | Huỷ tin rao trên web rồi gửi lại. |
| 400 | NOT_SUPPORTED |
Giá gia hạn ghi trên đơn chưa hợp lệ. | Liên hệ hỗ trợ kèm order_code. |
| 400 | CONFIRM_REQUIRED |
Lệnh xoá WAF thiếu trường xác nhận. | Gửi confirm bằng đúng order_code — xoá không khôi phục được và KHÔNG hoàn tiền. |
| 409 | DOMAIN_NOT_VERIFIED |
Tên miền chưa được xác minh cho tài khoản này — lệnh CHƯA trừ tiền. data.record = bản ghi TXT cần thêm (null ⇒ chưa có mã — gọi /waf/verify-domain để nhận). |
Thêm bản ghi TXT rồi gọi /waf/verify-domain kèm check: true; xác minh xong gửi lại (dùng lại đúng Idempotency-Key được). |
| 409 | DOMAIN_IN_USE |
Tên miền đang được một WAF khác bảo vệ (hoặc cấu hình cũ của tên miền chưa gỡ xong) — lệnh CHƯA trừ tiền. | Xoá WAF cũ của tên miền (nếu là của bạn) rồi thử lại sau ít phút; không phải của bạn ⇒ liên hệ hỗ trợ. |
| 409 | OUT_OF_STOCK |
Hệ thống WAF tạm hết chỗ (danh mục ghi in_stock: false) — lệnh mua CHƯA trừ tiền. |
Thử lại sau. |
| 409 | PRICE_CHANGED |
Số sẽ trừ vừa đổi giữa lúc kiểm và lúc trừ — mua: giá chu kỳ vừa tăng · gia hạn: giá / chu kỳ ghi trên đơn vừa đổi (lệnh đổi chu kỳ chen giữa). Lệnh CHƯA trừ đồng nào; data.price_buy (+ billing_cycle) = số mới. |
Báo giá lại (/waf/quote) rồi gửi lệnh mới (Idempotency-Key mới). |
| 409 | ORDER_EXPIRED |
WAF đã hết hạn hẳn / đã xoá, hoặc đã quá hạn chót gia hạn (renew_deadline — 7 ngày sau hạn) — không gia hạn được nữa. |
Mua WAF mới (/waf/buy) — tên miền dùng lại được khi cấu hình cũ gỡ xong. |
| 409 | RENEW_REQUIRED |
WAF đang tạm ngưng vì quá hạn (truy cập bị chặn) — đổi backend bị chặn tới khi gia hạn. | Gia hạn (/waf/renew) rồi thao tác lại. |
| 409 | PROVISIONING |
WAF đang được hoàn tất khởi tạo — lúc này chưa đổi backend được. | Hỏi /waf/info tới khi provision_status = ready. |
| 429 | COOLDOWN |
Đơn vừa nhận lệnh cùng nhóm (gia hạn: 60 giây · đổi backend: 60 giây · tự gia hạn: 5 giây), hôm nay đơn đã có một lượt gia hạn — kể cả ngày mua (Retry-After tới 0 giờ), hoặc vừa kiểm bản ghi xác minh của tên miền (10 giây). | Chờ Retry-After giây. |
| 503 | UNAVAILABLE |
Chưa đọc được dữ liệu / bằng chứng tên miền / danh sách địa chỉ bị cấm làm backend lúc này, hoặc tra DNS hỏng khi xác minh — lệnh CHƯA trừ tiền. | Thử lại sau ít phút — lệnh trừ tiền dùng lại đúng Idempotency-Key được. |
| 429 | IN_PROGRESS |
Đơn đang xử lý một lệnh khác (hai lệnh cùng lúc trên một WAF), hoặc đơn vừa thay đổi giữa lúc kiểm và lúc ghi. | Chờ Retry-After giây rồi gửi lại. |
/waf/products
Chỉ đọcDanh mục WAF: một sản phẩm (WAF cho một tên miền) — không còn chu kỳ nào đang bán thì danh sách rỗng. in_stock = còn chỗ trên máy chủ bảo vệ (hết chỗ vẫn bày — lệnh mua 409 OUT_OF_STOCK; ?in_stock=1 ⇒ hết chỗ thì danh sách rỗng). cycles = chu kỳ mua được (ngắn → dài); pricing[chu kỳ] = amount (đã trừ chiết khấu đại lý) · amount_original (giá niêm yết) · months · per_month. domain_verification = cách xác minh quyền tên miền bằng bản ghi TXT trước khi mua (record_prefix · valid_days) — tên miền mua tại đây đang chạy trong tài khoản thì khỏi TXT.
GET https://cloudmoon.net/api/v1/waf/products| Tham số | Vị trí | Bắt buộc | Mô tả |
|---|---|---|---|
in_stock |
query | không | 1 = chỉ bày khi còn chỗ (bỏ trống / 0 = luôn bày) |
curl 'https://cloudmoon.net/api/v1/waf/products' \
-H 'X-API-Key: ak_...'import requests
r = requests.get(
"https://cloudmoon.net/api/v1/waf/products",
headers={"X-API-Key": "ak_..."},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
const res = await fetch("https://cloudmoon.net/api/v1/waf/products", {
headers: { "X-API-Key": "ak_..." },
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('GET', '/v1/waf/products');
print_r($kq);{
"status": "success",
"msg": "OK",
"data": {
"items": [
{
"product": "waf",
"name": "WAF Tường lửa",
"in_stock": true,
"cycles": [
"onemonth",
"sixmonth",
"oneyear",
"twoyear",
"threeyear"
],
"pricing": {
"onemonth": {
"amount": 250000,
"amount_original": 250000,
"months": 1,
"per_month": 250000
},
"sixmonth": {
"amount": 1350000,
"amount_original": 1350000,
"months": 6,
"per_month": 225000
},
"oneyear": {
"amount": 2400000,
"amount_original": 2400000,
"months": 12,
"per_month": 200000
},
"twoyear": {
"amount": 4500000,
"amount_original": 4500000,
"months": 24,
"per_month": 187500
},
"threeyear": {
"amount": 6300000,
"amount_original": 6300000,
"months": 36,
"per_month": 175000
}
}
}
],
"total": 1,
"discount_percent": 0,
"currency": "VND",
"domain_verification": {
"type": "TXT",
"record_prefix": "_waf-verify",
"valid_days": 7
}
}
}/waf/price
Chỉ đọcBảng giá theo chu kỳ (khuôn cũ của web con — danh mục đầy đủ ở /waf/products): cycles[chu kỳ] = months · amount (đã trừ chiết khấu đại lý) · amount_original; chỉ chu kỳ đang bán. in_stock = còn chỗ trên máy chủ bảo vệ.
GET https://cloudmoon.net/api/v1/waf/priceKhông có tham số — chỉ cần header X-API-Key.
curl 'https://cloudmoon.net/api/v1/waf/price' \
-H 'X-API-Key: ak_...'import requests
r = requests.get(
"https://cloudmoon.net/api/v1/waf/price",
headers={"X-API-Key": "ak_..."},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
const res = await fetch("https://cloudmoon.net/api/v1/waf/price", {
headers: { "X-API-Key": "ak_..." },
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('GET', '/v1/waf/price');
print_r($kq);{
"status": "success",
"msg": "OK",
"data": {
"cycles": {
"onemonth": {
"months": 1,
"amount": 250000,
"amount_original": 250000
},
"oneyear": {
"months": 12,
"amount": 2400000,
"amount_original": 2400000
}
},
"discount_percent": 0,
"in_stock": true
}
}/waf/verify-domain
Toàn quyềnXác minh bạn quản lý tên miền để MUA WAF cho nó (bắt buộc với mua mới). Tên miền mua tại đây đang chạy trong tài khoản, hoặc đã xác minh TXT trong 7 ngày ⇒ verified: true ngay (proof: registered_here · txt). Còn lại ⇒ record = bản ghi TXT cần thêm (tên _waf-verify.<tên miền>, giá trị = mã 32 ký tự riêng cho cặp tài khoản + tên miền, không đổi); thêm xong gọi lại kèm check: true ⇒ hệ thống tra DNS (lượt vừa cấp mã chưa tra — checked: false): đạt ⇒ verified: true, chưa thấy ⇒ verified: false + result (not_found · wrong_value · cname — bản ghi phải là TXT đặt đúng tên, CNAME không tính). Đừng gửi check: true trước khi thêm bản ghi: hệ thống DNS có thể nhớ "chưa có" một thời gian (tới vài phút hoặc lâu hơn, tuỳ cấu hình DNS của tên miền). Nhịp: 10 giây / tên miền giữa hai lần kiểm · 30 lần kiểm / giờ · 30 tên miền mới / 24 giờ (429). Lệnh này KHÔNG cho biết tên miền có đang được bảo vệ hay không. Cần khoá Toàn quyền (cấp mã = ghi).
POST https://cloudmoon.net/api/v1/waf/verify-domain| Tham số | Vị trí | Bắt buộc | Mô tả |
|---|---|---|---|
domain |
body | có | tên miền cần bảo vệ (vd shop.congty.vn) |
check |
body | không | true = tra bản ghi TXT ngay (mặc định false — chỉ lấy bản ghi cần thêm) |
Chạy thử Gửi kèm X-Sandbox: 1: máy chủ kiểm như lượt thật rồi trả kết quả mô phỏng cùng khuôn — không trừ tiền, không đổi gì. Kịch bản lỗi (X-Sandbox-Scenario): RATE_LIMITED (429) · COOLDOWN (429) · UNAVAILABLE (503).
curl -X POST 'https://cloudmoon.net/api/v1/waf/verify-domain' \
-H 'X-API-Key: ak_...' \
-H 'Content-Type: application/json' \
-d '{"domain":"shop.congty.vn","check":true}'import requests
r = requests.post(
"https://cloudmoon.net/api/v1/waf/verify-domain",
headers={"X-API-Key": "ak_..."},
json={"domain": "shop.congty.vn", "check": True},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
const res = await fetch("https://cloudmoon.net/api/v1/waf/verify-domain", {
method: "POST",
headers: {
"X-API-Key": "ak_...",
"Content-Type": "application/json",
},
body: JSON.stringify({ domain: "shop.congty.vn", check: true }),
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('POST', '/v1/waf/verify-domain', ['domain' => 'shop.congty.vn', 'check' => true]);
print_r($kq);{
"domain": "shop.congty.vn",
"check": true
}{
"status": "success",
"msg": "Xác minh tên miền thành công",
"data": {
"domain": "shop.congty.vn",
"verified": true,
"proof": "txt",
"verified_at": "2026-10-20T09:15:00+07:00",
"record": null,
"checked": true,
"result": "verified"
}
}/waf/quote
Chỉ đọcBÁO GIÁ — không trừ tiền, không ghi gì, khoá chỉ đọc gọi được. type buy (mặc định): CÙNG thân và CÙNG bộ kiểm với /waf/buy (tên miền chưa xác minh ⇒ 409 DOMAIN_NOT_VERIFIED · tên miền đang được một WAF khác bảo vệ / cấu hình cũ chưa gỡ xong ⇒ 409 DOMAIN_IN_USE · backend sai ⇒ 400 · hết chỗ ⇒ 409) ⇒ amount = số sẽ trừ (đã chiết khấu), time_expire dự kiến, enough so với balance_available (= số dư − tiền các lệnh mua VPS còn chờ tạo máy). Đơn có sẵn: type renew + order_code ⇒ amount = số lượt gia hạn sẽ trừ (giá ghi trên đơn) + time_expire mới + reopened (true = đơn đang tạm ngưng, gia hạn sẽ mở lại); type change_cycle + order_code + billing_cycle ⇒ amount 0 (đổi chu kỳ không thu tiền) + price_buy = giá lần gia hạn kế ở chu kỳ mới. Bảo trì chỉ chặn báo giá mua mới.
POST https://cloudmoon.net/api/v1/waf/quote| Tham số | Vị trí | Bắt buộc | Mô tả |
|---|---|---|---|
type |
body | không | buy (mặc định) | renew | change_cycle |
order_code |
body | không | renew / change_cycle: mã đơn có sẵn |
domain |
body | không | buy: tên miền cần bảo vệ |
backend_upstream |
body | không | buy: IP công khai:cổng của máy chủ gốc, vd http://1.2.3.4:80 |
billing_cycle |
body | không | buy: một mã trong cycles của /waf/products (mặc định onemonth) · change_cycle: chu kỳ mới |
name |
body | không | buy: tên gợi nhớ (≤ 200 ký tự) |
Chạy thử Lệnh đọc — gửi kèm X-Sandbox: 1 vẫn chạy như thường (không đổi gì). Nhận cả mã SANDBOX… của lệnh mua chạy thử ⇒ trả máy mẫu.
curl -X POST 'https://cloudmoon.net/api/v1/waf/quote' \
-H 'X-API-Key: ak_...' \
-H 'Content-Type: application/json' \
-d '{"domain":"shop.congty.vn","backend_upstream":"http://1.2.3.4:80","billing_cycle":"oneyear"}'import requests
r = requests.post(
"https://cloudmoon.net/api/v1/waf/quote",
headers={"X-API-Key": "ak_..."},
json={"domain": "shop.congty.vn", "backend_upstream": "http://1.2.3.4:80", "billing_cycle": "oneyear"},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
const res = await fetch("https://cloudmoon.net/api/v1/waf/quote", {
method: "POST",
headers: {
"X-API-Key": "ak_...",
"Content-Type": "application/json",
},
body: JSON.stringify({ domain: "shop.congty.vn", backend_upstream: "http://1.2.3.4:80", billing_cycle: "oneyear" }),
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('POST', '/v1/waf/quote', ['domain' => 'shop.congty.vn', 'backend_upstream' => 'http://1.2.3.4:80', 'billing_cycle' => 'oneyear']);
print_r($kq);{
"domain": "shop.congty.vn",
"backend_upstream": "http://1.2.3.4:80",
"billing_cycle": "oneyear"
}{
"status": "success",
"msg": "OK",
"data": {
"type": "buy",
"domain": "shop.congty.vn",
"backend_upstream": "http://1.2.3.4:80",
"billing_cycle": "oneyear",
"months": 12,
"amount": 2400000,
"amount_original": 2400000,
"discount_percent": 0,
"time_expire": "2027-10-20 09:30:00",
"currency": "VND",
"balance": 3000000,
"balance_available": 3000000,
"enough": true
}
}/waf/buy
Toàn quyềnMua WAF cho MỘT tên miền — trừ tiền và dựng cấu hình bảo vệ NGAY trong lượt gọi: HTTP 200 provision_status = ready (trỏ bản ghi A về dns.value là WAF lọc ngay). Máy chủ bảo vệ trục trặc SAU khi đã trừ ⇒ HTTP 202 provisioning + charged: true (đơn đã có, hệ thống tự hoàn tất — hỏi /waf/info). Tên miền phải được xác minh trước (/waf/verify-domain) — thiếu ⇒ 409 DOMAIN_NOT_VERIFIED (data.record = bản ghi TXT cần thêm; null ⇒ chưa có mã, gọi verify-domain). Tên miền đang được một WAF khác bảo vệ, hoặc cấu hình cũ của nó chưa gỡ xong ⇒ 409 DOMAIN_IN_USE · hết chỗ ⇒ 409 OUT_OF_STOCK · giá vừa tăng giữa lúc kiểm và lúc trừ ⇒ 409 PRICE_CHANGED (data.price_buy) — các lỗi này CHƯA trừ tiền. Gửi lại cùng Idempotency-Key ⇒ phát lại câu trả lời, không trừ lần hai. Đơn mới BẬT SẴN tự gia hạn (renew_auto on) — chỉ mua một kỳ thì tắt bằng /waf/auto-renew. Mua xong không gia hạn được ngay trong ngày (lượt gia hạn kế từ 0 giờ hôm sau). Giới hạn lượt mua / giờ: xem mục Giới hạn.
POST https://cloudmoon.net/api/v1/waf/buy| Tham số | Vị trí | Bắt buộc | Mô tả |
|---|---|---|---|
Idempotency-Key |
header | không | chống trừ tiền hai lần khi gửi lại |
domain |
body | có | tên miền cần bảo vệ — đã xác minh (/waf/verify-domain) |
backend_upstream |
body | có | IP công khai:cổng của máy chủ gốc, vd http://1.2.3.4:80 — địa chỉ nội bộ bị chối; tên miền được phân giải rồi lưu thành IP |
billing_cycle |
body | không | một mã trong cycles của /waf/products (mặc định onemonth) |
name |
body | không | tên gợi nhớ (≤ 200 ký tự; bỏ trống = tên miền) |
Chạy thử Gửi kèm X-Sandbox: 1: máy chủ kiểm như lượt thật rồi trả kết quả mô phỏng cùng khuôn — không trừ tiền, không đổi gì. Kịch bản lỗi (X-Sandbox-Scenario): INSUFFICIENT_BALANCE (402) · DOMAIN_NOT_VERIFIED (409) · DOMAIN_IN_USE (409) · OUT_OF_STOCK (409) · PRICE_CHANGED (409) · IDEMPOTENCY_PENDING (409) · RATE_LIMITED (429) · BUSY (429) · SERVICE_DISABLED (503) · UNAVAILABLE (503) · FAILED (400) · PROVISION_FAILED (lệnh vẫn nhận, info về sau báo failed).
curl -X POST 'https://cloudmoon.net/api/v1/waf/buy' \
-H 'X-API-Key: ak_...' \
-H 'Idempotency-Key: 7f9c2e4b-1a2b-4c3d-9e8f-0123456789ab' \
-H 'Content-Type: application/json' \
-d '{"domain":"shop.congty.vn","backend_upstream":"http://1.2.3.4:80","billing_cycle":"onemonth"}'import uuid
import requests
r = requests.post(
"https://cloudmoon.net/api/v1/waf/buy",
headers={"X-API-Key": "ak_...", "Idempotency-Key": str(uuid.uuid4())},
json={"domain": "shop.congty.vn", "backend_upstream": "http://1.2.3.4:80", "billing_cycle": "onemonth"},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
import { randomUUID } from "node:crypto";
const res = await fetch("https://cloudmoon.net/api/v1/waf/buy", {
method: "POST",
headers: {
"X-API-Key": "ak_...",
"Content-Type": "application/json",
"Idempotency-Key": randomUUID(),
},
body: JSON.stringify({ domain: "shop.congty.vn", backend_upstream: "http://1.2.3.4:80", billing_cycle: "onemonth" }),
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('POST', '/v1/waf/buy', ['domain' => 'shop.congty.vn', 'backend_upstream' => 'http://1.2.3.4:80', 'billing_cycle' => 'onemonth'], bin2hex(random_bytes(16)));
print_r($kq);{
"domain": "shop.congty.vn",
"backend_upstream": "http://1.2.3.4:80",
"billing_cycle": "onemonth"
}{
"status": "success",
"msg": "Đã kích hoạt WAF",
"data": {
"order_code": "201026WAFA1B2C3D4E5F6",
"domain": "shop.congty.vn",
"provision_status": "ready",
"charged": true,
"name": "shop.congty.vn",
"backend_upstream": "http://1.2.3.4:80",
"billing_cycle": "onemonth",
"price_buy": 250000,
"time_expire": "2026-11-20 09:30:00",
"node_ip": "203.0.113.20",
"dns": {
"type": "A",
"name": "shop.congty.vn",
"value": "203.0.113.20"
},
"provisioning": false,
"note": "Trỏ bản ghi A của tên miền về dns.value — WAF lọc truy cập ngay khi DNS cập nhật."
}
}/waf/list
Chỉ đọcMọi WAF của tài khoản: provision_status (ready · provisioning — đang hoàn tất cấu hình · suspended — tạm ngưng vì quá hạn, truy cập bị chặn (lệnh chặn có thể trễ ít phút) · expired — hết hạn / đã xoá), dns (bản ghi A cần trỏ; null khi đã hết), billing (price_renew = số lượt gia hạn kế tiếp sẽ trừ — giá ghi trên đơn; null khi trạng thái đơn không cho gia hạn — đã gia hạn hôm nay hay thiếu tiền không làm nó null), allowed_actions. ?status= active | pending_expired | expired (bỏ trống = mọi đơn). Phân trang.
GET https://cloudmoon.net/api/v1/waf/list| Tham số | Vị trí | Bắt buộc | Mô tả |
|---|---|---|---|
status |
query | không | active | pending_expired | expired |
limit |
query | không | 1-200, mặc định 50 |
page |
query | không | Trang, tính từ 1 |
curl 'https://cloudmoon.net/api/v1/waf/list' \
-H 'X-API-Key: ak_...'import requests
r = requests.get(
"https://cloudmoon.net/api/v1/waf/list",
headers={"X-API-Key": "ak_..."},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
const res = await fetch("https://cloudmoon.net/api/v1/waf/list", {
headers: { "X-API-Key": "ak_..." },
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('GET', '/v1/waf/list');
print_r($kq);{
"status": "success",
"msg": "OK",
"data": {
"items": [
{
"order_code": "201026WAFA1B2C3D4E5F6",
"name": "shop.congty.vn",
"domain": "shop.congty.vn",
"backend_upstream": "http://1.2.3.4:80",
"server_ip": "203.0.113.20",
"price_buy": 250000,
"billing_cycle": "onemonth",
"renew_auto": "on",
"order_status": "active",
"time_buy": "2026-10-20 09:30:00",
"time_renewal": "2026-10-20",
"time_expire": "2026-11-20 09:30:00",
"provision_status": "ready",
"charged": true,
"dns": {
"type": "A",
"name": "shop.congty.vn",
"value": "203.0.113.20"
},
"billing": {
"price_buy": 250000,
"price_renew": 250000,
"billing_cycle": "onemonth",
"months": 1,
"renew_auto": "on",
"time_buy": "2026-10-20 09:30:00",
"time_expire": "2026-11-20 09:30:00"
},
"allowed_actions": [
"renew",
"auto_renew",
"change_cycle",
"set_backend",
"delete"
]
}
],
"page": 1,
"limit": 50,
"total": 1
}
}/waf/info
Chỉ đọcChi tiết một WAF: mọi trường của /waf/list + renew_until (hạn mới nếu gia hạn ngay — dự tính, chưa xét lượt gia hạn trong ngày hay số dư; null khi trạng thái đơn không cho gia hạn) + renew_deadline (hạn chót gia hạn = time_expire + 7 ngày — từ mốc này không gia hạn được nữa, cấu hình bị xoá ở lượt kiểm sau đó, phải mua mới). order_status: active · pending_expired (tạm ngưng — truy cập bị chặn, lệnh chặn có thể trễ ít phút; lệnh ghi còn gia hạn / tự gia hạn / đổi chu kỳ / xoá) · expired (hết hạn hẳn / đã xoá — không còn lệnh ghi nào; info vẫn đọc được, stats available false, log cũ đọc qua /waf/logs không lọc order_code).
GET https://cloudmoon.net/api/v1/waf/info| Tham số | Vị trí | Bắt buộc | Mô tả |
|---|---|---|---|
order_code |
query | có | Mã đơn (order_code) — lấy từ lệnh mua hoặc /list |
Chạy thử Nhận cả mã SANDBOX… của lệnh mua chạy thử ⇒ trả máy mẫu.
curl 'https://cloudmoon.net/api/v1/waf/info?order_code=201026WAFA1B2C3D4E5F6' \
-H 'X-API-Key: ak_...'import requests
r = requests.get(
"https://cloudmoon.net/api/v1/waf/info",
headers={"X-API-Key": "ak_..."},
params={"order_code": "201026WAFA1B2C3D4E5F6"},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
const res = await fetch("https://cloudmoon.net/api/v1/waf/info?order_code=201026WAFA1B2C3D4E5F6", {
headers: { "X-API-Key": "ak_..." },
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('GET', '/v1/waf/info?order_code=201026WAFA1B2C3D4E5F6');
print_r($kq);{
"status": "success",
"msg": "OK",
"data": {
"order_code": "201026WAFA1B2C3D4E5F6",
"name": "shop.congty.vn",
"domain": "shop.congty.vn",
"backend_upstream": "http://1.2.3.4:80",
"server_ip": "203.0.113.20",
"price_buy": 250000,
"billing_cycle": "onemonth",
"renew_auto": "on",
"order_status": "active",
"time_buy": "2026-10-20 09:30:00",
"time_renewal": "2026-10-20",
"time_expire": "2026-11-20 09:30:00",
"provision_status": "ready",
"charged": true,
"dns": {
"type": "A",
"name": "shop.congty.vn",
"value": "203.0.113.20"
},
"billing": {
"price_buy": 250000,
"price_renew": 250000,
"billing_cycle": "onemonth",
"months": 1,
"renew_auto": "on",
"time_buy": "2026-10-20 09:30:00",
"time_expire": "2026-11-20 09:30:00"
},
"renew_until": "2026-12-20 09:30:00",
"renew_deadline": "2026-11-27 09:30:00",
"allowed_actions": [
"renew",
"auto_renew",
"change_cycle",
"set_backend",
"delete"
]
}
}/waf/renew
Toàn quyềnGia hạn một WAF thêm MỘT chu kỳ (chu kỳ ghi trên đơn) — trừ ví NGAY (báo giá: /waf/quote type renew). amount = giá ghi trên đơn (billing.price_renew). Hạn mới = max(bây giờ, hạn cũ) + một chu kỳ. Đơn tạm ngưng ⇒ gia hạn mở lại bảo vệ (reopened: true; false = đã trừ tiền, bảo vệ đang được mở lại — hệ thống tự hoàn tất). Từ hạn chót (renew_deadline) ⇒ 409 ORDER_EXPIRED. Mỗi đơn một lượt gia hạn mỗi ngày, tính cả ngày mua (429 COOLDOWN tới 0 giờ). Giá ghi trên đơn vừa tăng hoặc chu kỳ vừa đổi giữa lúc kiểm và lúc trừ ⇒ 409 PRICE_CHANGED (chưa trừ tiền). Bảo trì không chặn gia hạn.
POST https://cloudmoon.net/api/v1/waf/renew| Tham số | Vị trí | Bắt buộc | Mô tả |
|---|---|---|---|
Idempotency-Key |
header | không | chống trừ tiền hai lần khi gửi lại |
order_code |
body | có | Mã đơn (order_code) — lấy từ lệnh mua hoặc /list |
Chạy thử Gửi kèm X-Sandbox: 1: máy chủ kiểm như lượt thật rồi trả kết quả mô phỏng cùng khuôn — không trừ tiền, không đổi gì. Nhận cả mã SANDBOX… của lệnh mua chạy thử ⇒ trả máy mẫu. Kịch bản lỗi (X-Sandbox-Scenario): INSUFFICIENT_BALANCE (402) · ORDER_EXPIRED (409) · PRICE_CHANGED (409) · IDEMPOTENCY_PENDING (409) · COOLDOWN (429) · IN_PROGRESS (429) · BUSY (429) · UNAVAILABLE (503) · NOT_SUPPORTED (400) · FAILED (400).
curl -X POST 'https://cloudmoon.net/api/v1/waf/renew' \
-H 'X-API-Key: ak_...' \
-H 'Idempotency-Key: 7f9c2e4b-1a2b-4c3d-9e8f-0123456789ab' \
-H 'Content-Type: application/json' \
-d '{"order_code":"201026WAFA1B2C3D4E5F6"}'import uuid
import requests
r = requests.post(
"https://cloudmoon.net/api/v1/waf/renew",
headers={"X-API-Key": "ak_...", "Idempotency-Key": str(uuid.uuid4())},
json={"order_code": "201026WAFA1B2C3D4E5F6"},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
import { randomUUID } from "node:crypto";
const res = await fetch("https://cloudmoon.net/api/v1/waf/renew", {
method: "POST",
headers: {
"X-API-Key": "ak_...",
"Content-Type": "application/json",
"Idempotency-Key": randomUUID(),
},
body: JSON.stringify({ order_code: "201026WAFA1B2C3D4E5F6" }),
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('POST', '/v1/waf/renew', ['order_code' => '201026WAFA1B2C3D4E5F6'], bin2hex(random_bytes(16)));
print_r($kq);{
"order_code": "201026WAFA1B2C3D4E5F6"
}{
"status": "success",
"msg": "Gia hạn thành công",
"data": {
"order_code": "201026WAFA1B2C3D4E5F6",
"amount": 250000,
"price_buy": 250000,
"billing_cycle": "onemonth",
"months": 1,
"time_expire": "2026-12-20 09:30:00",
"reopened": null
}
}/waf/auto-renew
Toàn quyềnĐẶT tự gia hạn (không lật — gửi lại cùng giá trị vẫn thành công, sau nhịp 5 giây). Bật ⇒ mỗi giờ, từ lúc còn ≤ 7 ngày tới time_expire (kể cả khi đơn đã tạm ngưng, tới hạn chót), hệ thống tự trừ ví gia hạn một chu kỳ — giữ chu kỳ, cùng giá với /waf/renew; số dư thiếu ⇒ bỏ qua, thử lại giờ sau. Đơn hết hạn hẳn / đã xoá, hoặc đã tới hạn chót ⇒ 409 ORDER_EXPIRED (đơn tạm ngưng còn trước hạn chót vẫn đặt được). Nhịp 5 giây / đơn.
POST https://cloudmoon.net/api/v1/waf/auto-renew| Tham số | Vị trí | Bắt buộc | Mô tả |
|---|---|---|---|
order_code |
body | có | Mã đơn (order_code) — lấy từ lệnh mua hoặc /list |
enabled |
body | có | true / false |
Chạy thử Gửi kèm X-Sandbox: 1: máy chủ kiểm như lượt thật rồi trả kết quả mô phỏng cùng khuôn — không trừ tiền, không đổi gì. Nhận cả mã SANDBOX… của lệnh mua chạy thử ⇒ trả máy mẫu. Kịch bản lỗi (X-Sandbox-Scenario): ORDER_EXPIRED (409) · COOLDOWN (429) · IN_PROGRESS (429) · BUSY (429) · FAILED (400).
curl -X POST 'https://cloudmoon.net/api/v1/waf/auto-renew' \
-H 'X-API-Key: ak_...' \
-H 'Content-Type: application/json' \
-d '{"order_code":"201026WAFA1B2C3D4E5F6","enabled":false}'import requests
r = requests.post(
"https://cloudmoon.net/api/v1/waf/auto-renew",
headers={"X-API-Key": "ak_..."},
json={"order_code": "201026WAFA1B2C3D4E5F6", "enabled": False},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
const res = await fetch("https://cloudmoon.net/api/v1/waf/auto-renew", {
method: "POST",
headers: {
"X-API-Key": "ak_...",
"Content-Type": "application/json",
},
body: JSON.stringify({ order_code: "201026WAFA1B2C3D4E5F6", enabled: false }),
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('POST', '/v1/waf/auto-renew', ['order_code' => '201026WAFA1B2C3D4E5F6', 'enabled' => false]);
print_r($kq);{
"order_code": "201026WAFA1B2C3D4E5F6",
"enabled": false
}{
"status": "success",
"msg": "Đã tắt tự gia hạn",
"data": {
"order_code": "201026WAFA1B2C3D4E5F6",
"renew_auto": "off"
}
}/waf/change-cycle
Toàn quyềnĐổi chu kỳ cho LẦN GIA HẠN SAU — không trừ tiền, không đổi hạn (amount 0): price_buy = giá chu kỳ mới hiện hành, đã trừ chiết khấu đại lý của tài khoản (như lúc mua) — lần gia hạn kế thu số này. Cùng chu kỳ đang dùng ⇒ thành công, không đổi gì (changed: false). Chu kỳ không đang bán ⇒ 400 · đang rao bán trên chợ ⇒ 409 LISTED_ON_MARKETPLACE · đơn hết hạn ⇒ 409 ORDER_EXPIRED.
POST https://cloudmoon.net/api/v1/waf/change-cycle| Tham số | Vị trí | Bắt buộc | Mô tả |
|---|---|---|---|
order_code |
body | có | Mã đơn (order_code) — lấy từ lệnh mua hoặc /list |
billing_cycle |
body | có | một mã trong cycles của /waf/products |
Chạy thử Gửi kèm X-Sandbox: 1: máy chủ kiểm như lượt thật rồi trả kết quả mô phỏng cùng khuôn — không trừ tiền, không đổi gì. Nhận cả mã SANDBOX… của lệnh mua chạy thử ⇒ trả máy mẫu. Kịch bản lỗi (X-Sandbox-Scenario): LISTED_ON_MARKETPLACE (409) · ORDER_EXPIRED (409) · IN_PROGRESS (429) · BUSY (429) · FAILED (400).
curl -X POST 'https://cloudmoon.net/api/v1/waf/change-cycle' \
-H 'X-API-Key: ak_...' \
-H 'Content-Type: application/json' \
-d '{"order_code":"201026WAFA1B2C3D4E5F6","billing_cycle":"oneyear"}'import requests
r = requests.post(
"https://cloudmoon.net/api/v1/waf/change-cycle",
headers={"X-API-Key": "ak_..."},
json={"order_code": "201026WAFA1B2C3D4E5F6", "billing_cycle": "oneyear"},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
const res = await fetch("https://cloudmoon.net/api/v1/waf/change-cycle", {
method: "POST",
headers: {
"X-API-Key": "ak_...",
"Content-Type": "application/json",
},
body: JSON.stringify({ order_code: "201026WAFA1B2C3D4E5F6", billing_cycle: "oneyear" }),
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('POST', '/v1/waf/change-cycle', ['order_code' => '201026WAFA1B2C3D4E5F6', 'billing_cycle' => 'oneyear']);
print_r($kq);{
"order_code": "201026WAFA1B2C3D4E5F6",
"billing_cycle": "oneyear"
}{
"status": "success",
"msg": "Đã đổi chu kỳ. Áp dụng cho lần gia hạn kế tiếp.",
"data": {
"order_code": "201026WAFA1B2C3D4E5F6",
"billing_cycle": "oneyear",
"months": 12,
"price_buy": 2400000,
"amount": 0,
"changed": true
}
}/waf/set-backend
Toàn quyềnĐổi máy chủ gốc mà WAF chuyển truy cập sạch về: http(s):// + IP công khai hoặc tên miền (phân giải IPv4 lúc lưu, lưu thành IP) + cổng tuỳ chọn. applied: true = máy chủ bảo vệ đã nhận; false = đã lưu, hệ thống đang áp (tự thử lại, vài phút). Gửi lại đúng backend đang dùng ⇒ áp lại cấu hình. Đơn tạm ngưng ⇒ 409 RENEW_REQUIRED (gia hạn trước) · đơn mua xong mà cấu hình bảo vệ chưa dựng xong (lệnh mua 202) ⇒ 409 PROVISIONING · đơn hết hạn ⇒ 409 ORDER_EXPIRED. Nhịp 60 giây / đơn.
POST https://cloudmoon.net/api/v1/waf/set-backend| Tham số | Vị trí | Bắt buộc | Mô tả |
|---|---|---|---|
order_code |
body | có | Mã đơn (order_code) — lấy từ lệnh mua hoặc /list |
backend_upstream |
body | có | IP công khai:cổng của máy chủ gốc, vd http://1.2.3.4:80 — địa chỉ nội bộ bị chối; tên miền được phân giải rồi lưu thành IP |
Chạy thử Gửi kèm X-Sandbox: 1: máy chủ kiểm như lượt thật rồi trả kết quả mô phỏng cùng khuôn — không trừ tiền, không đổi gì. Nhận cả mã SANDBOX… của lệnh mua chạy thử ⇒ trả máy mẫu. Kịch bản lỗi (X-Sandbox-Scenario): RENEW_REQUIRED (409) · PROVISIONING (409) · ORDER_EXPIRED (409) · COOLDOWN (429) · IN_PROGRESS (429) · BUSY (429) · UNAVAILABLE (503) · FAILED (400).
curl -X POST 'https://cloudmoon.net/api/v1/waf/set-backend' \
-H 'X-API-Key: ak_...' \
-H 'Content-Type: application/json' \
-d '{"order_code":"201026WAFA1B2C3D4E5F6","backend_upstream":"http://5.6.7.8:80"}'import requests
r = requests.post(
"https://cloudmoon.net/api/v1/waf/set-backend",
headers={"X-API-Key": "ak_..."},
json={"order_code": "201026WAFA1B2C3D4E5F6", "backend_upstream": "http://5.6.7.8:80"},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
const res = await fetch("https://cloudmoon.net/api/v1/waf/set-backend", {
method: "POST",
headers: {
"X-API-Key": "ak_...",
"Content-Type": "application/json",
},
body: JSON.stringify({ order_code: "201026WAFA1B2C3D4E5F6", backend_upstream: "http://5.6.7.8:80" }),
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('POST', '/v1/waf/set-backend', ['order_code' => '201026WAFA1B2C3D4E5F6', 'backend_upstream' => 'http://5.6.7.8:80']);
print_r($kq);{
"order_code": "201026WAFA1B2C3D4E5F6",
"backend_upstream": "http://5.6.7.8:80"
}{
"status": "success",
"msg": "Đã cập nhật backend",
"data": {
"order_code": "201026WAFA1B2C3D4E5F6",
"backend_upstream": "http://5.6.7.8:80",
"applied": true
}
}/waf/delete
Toàn quyềnXOÁ một WAF — KHÔNG hoàn tiền, không khôi phục được (confirm = order_code): đơn chuyển expired ngay, cấu hình bảo vệ được gỡ (có thể hoàn tất sau ít phút); tên miền dùng lại được khi gỡ xong. Đang rao bán trên chợ ⇒ 409 LISTED_ON_MARKETPLACE · đã hết hạn / đã xoá ⇒ 409 ORDER_EXPIRED. Đường cũ /api/webcon/waf/delete trỏ cùng lệnh (thân cũ chỉ order_code vẫn nhận ở đường cũ).
POST https://cloudmoon.net/api/v1/waf/delete| Tham số | Vị trí | Bắt buộc | Mô tả |
|---|---|---|---|
order_code |
body | có | Mã đơn (order_code) — lấy từ lệnh mua hoặc /list |
confirm |
body | có | bằng đúng order_code |
Chạy thử Gửi kèm X-Sandbox: 1: máy chủ kiểm như lượt thật rồi trả kết quả mô phỏng cùng khuôn — không trừ tiền, không đổi gì. Nhận cả mã SANDBOX… của lệnh mua chạy thử ⇒ trả máy mẫu. Kịch bản lỗi (X-Sandbox-Scenario): LISTED_ON_MARKETPLACE (409) · ORDER_EXPIRED (409) · IN_PROGRESS (429) · BUSY (429) · FAILED (400).
curl -X POST 'https://cloudmoon.net/api/v1/waf/delete' \
-H 'X-API-Key: ak_...' \
-H 'Content-Type: application/json' \
-d '{"order_code":"201026WAFA1B2C3D4E5F6","confirm":"201026WAFA1B2C3D4E5F6"}'import requests
r = requests.post(
"https://cloudmoon.net/api/v1/waf/delete",
headers={"X-API-Key": "ak_..."},
json={"order_code": "201026WAFA1B2C3D4E5F6", "confirm": "201026WAFA1B2C3D4E5F6"},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
const res = await fetch("https://cloudmoon.net/api/v1/waf/delete", {
method: "POST",
headers: {
"X-API-Key": "ak_...",
"Content-Type": "application/json",
},
body: JSON.stringify({ order_code: "201026WAFA1B2C3D4E5F6", confirm: "201026WAFA1B2C3D4E5F6" }),
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('POST', '/v1/waf/delete', ['order_code' => '201026WAFA1B2C3D4E5F6', 'confirm' => '201026WAFA1B2C3D4E5F6']);
print_r($kq);{
"order_code": "201026WAFA1B2C3D4E5F6",
"confirm": "201026WAFA1B2C3D4E5F6"
}{
"status": "success",
"msg": "Đã xoá WAF — không hoàn tiền",
"data": {
"order_code": "201026WAFA1B2C3D4E5F6",
"order_status": "expired",
"refunded": false
}
}/waf/logs
Chỉ đọcLog tấn công đã ghi nhận (mới nhất trước) của tài khoản — ?order_code= chỉ lấy log của tên miền hiện tại của đơn ấy (đơn đã hết hạn / đã xoá không còn tên miền ⇒ rỗng — log cũ vẫn có khi không lọc). attack_type: sqli · xss · rce · ssrf · xxe · ssti · file_inclusion · path_traversal · deserialization · backdoor · scanner · file_upload · other · risk_level (1 thấp · 2 trung bình · 3 cao; 0 = chưa xếp mức) · action 1 = chặn (blocked: true) · time = ISO 8601. Mỗi sự kiện gán cho đơn đang giữ tên miền lúc ghi nhận — mua lại tên miền bằng đơn mới không thấy log đời trước của tài khoản khác; chuyển quyền thì log đã có đi theo đơn sang người nhận. Log về theo nhịp kéo (khoảng 5 phút).
GET https://cloudmoon.net/api/v1/waf/logs| Tham số | Vị trí | Bắt buộc | Mô tả |
|---|---|---|---|
order_code |
query | không | chỉ log của một WAF |
limit |
query | không | 1-200, mặc định 50 |
page |
query | không | Trang, tính từ 1 |
Chạy thử Nhận cả mã SANDBOX… của lệnh mua chạy thử ⇒ trả máy mẫu.
curl 'https://cloudmoon.net/api/v1/waf/logs' \
-H 'X-API-Key: ak_...'import requests
r = requests.get(
"https://cloudmoon.net/api/v1/waf/logs",
headers={"X-API-Key": "ak_..."},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
const res = await fetch("https://cloudmoon.net/api/v1/waf/logs", {
headers: { "X-API-Key": "ak_..." },
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('GET', '/v1/waf/logs');
print_r($kq);{
"status": "success",
"msg": "OK",
"data": {
"items": [
{
"host": "shop.congty.vn",
"src_ip": "198.51.100.7",
"attack_type": "sqli",
"action": 1,
"blocked": true,
"url_path": "/login",
"risk_level": 3,
"event_time": "2026-10-20 10:00:00",
"time": "2026-10-20T10:00:00+07:00"
}
],
"page": 1,
"limit": 50,
"total": 1
}
}/waf/stats
Chỉ đọcLưu lượng HÔM NAY (từ 0 giờ, giờ Việt Nam) của một WAF: total_requests · blocked · passed · top_ips (tối đa 5 IP bị chặn nhiều nhất hôm nay ⇒ số lượt — lấy từ log đã kéo, có thể lệch ba số kia vài phút). Số làm mới tối đa mỗi 60 giây (synced_at; stale: true = số cũ hơn 60 giây); lượt truy cập mới hiện vào số sau khoảng 1–2 phút (máy chủ bảo vệ tổng hợp theo phút). Chưa có số ⇒ available: false và ba số null (không phải 0).
GET https://cloudmoon.net/api/v1/waf/stats| Tham số | Vị trí | Bắt buộc | Mô tả |
|---|---|---|---|
order_code |
query | có | Mã đơn (order_code) — lấy từ lệnh mua hoặc /list |
Chạy thử Gửi kèm X-Sandbox: 1: máy chủ kiểm như lượt thật rồi trả kết quả mô phỏng cùng khuôn — không trừ tiền, không đổi gì. Nhận cả mã SANDBOX… của lệnh mua chạy thử ⇒ trả máy mẫu.
curl 'https://cloudmoon.net/api/v1/waf/stats?order_code=201026WAFA1B2C3D4E5F6' \
-H 'X-API-Key: ak_...'import requests
r = requests.get(
"https://cloudmoon.net/api/v1/waf/stats",
headers={"X-API-Key": "ak_..."},
params={"order_code": "201026WAFA1B2C3D4E5F6"},
timeout=30,
)
print(r.status_code, r.json())// Node.js 18+ — lưu thành tệp .mjs
const res = await fetch("https://cloudmoon.net/api/v1/waf/stats?order_code=201026WAFA1B2C3D4E5F6", {
headers: { "X-API-Key": "ak_..." },
});
console.log(res.status, await res.json());// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('GET', '/v1/waf/stats?order_code=201026WAFA1B2C3D4E5F6');
print_r($kq);{
"status": "success",
"msg": "OK",
"data": {
"order_code": "201026WAFA1B2C3D4E5F6",
"domain": "shop.congty.vn",
"available": true,
"period": "today",
"total_requests": 12000,
"blocked": 34,
"passed": 11966,
"top_ips": {
"198.51.100.7": 20
},
"synced_at": "2026-10-20T10:01:00+07:00",
"stale": false
}
}