Tham chiếu API

API WAF

WAF tầng ứng dụng (L7) cho MỘT tên miền: trỏ bản ghi A của tên miền về dns.value (server_ip) — truy cập đi qua bộ lọc rồi mới tới máy chủ gốc (backend_upstream = IP công khai:cổng; tên miền được phân giải rồi lưu IP; địa chỉ nội bộ bị chối). KHÔNG chống tấn công DDoS băng thông lớn (L3/L4). Mua mới cần BẰNG CHỨNG bạn quản lý tên miền: tên miền mua tại đây đang chạy trong tài khoản, hoặc bản ghi TXT xác minh (/waf/verify-domain) kiểm đạt trong 7 ngày. Mua trừ tiền và dựng cấu hình bảo vệ NGAY trong lượt gọi (HTTP 200 provision_status ready; máy chủ bảo vệ trục trặc sau khi đã trừ ⇒ 202 provisioning — hệ thống tự hoàn tất). Hết hạn ⇒ ở lượt kiểm kế tiếp (mỗi 6 giờ) đơn tạm ngưng (suspended — truy cập bị chặn; lỗi tạm thời khi áp lệnh chặn thì hệ thống tự áp lại sau ít phút) tới hạn chót renew_deadline (7 ngày sau hạn): gia hạn trước mốc ấy để mở lại; từ hạn chót không gia hạn được nữa, cấu hình bị xoá ở lượt kiểm sau đó. HTTPS: bật proxy Cloudflare với SSL Flexible (không cần chứng chỉ trên WAF). Không qua API: chuyển quyền, rao bán trên chợ.

Trên trang này
  1. Tổng quan
  2. Mua & xác minh tên miền
  3. Trỏ DNS & HTTPS
  4. Máy chủ gốc (backend)
  5. Trạng thái đơn
  6. Gia hạn & tạm ngưng
  7. Log tấn công & thống kê
  8. Luật riêng
  9. Nhịp thao tác
  10. Mã lỗi riêng
  11. GET /waf/products
  12. GET /waf/price
  13. POST /waf/verify-domain
  14. POST /waf/quote
  15. POST /waf/buy
  16. GET /waf/list
  17. GET /waf/info
  18. POST /waf/renew
  19. POST /waf/auto-renew
  20. POST /waf/change-cycle
  21. POST /waf/set-backend
  22. POST /waf/delete
  23. GET /waf/logs
  24. GET /waf/stats

Tổng quan

Địa chỉ gốc của các endpoint trên trang này:

Base URL
https://cloudmoon.net/api/v1
EndpointViệcQuyề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).

  1. POST /waf/verify-domain vớ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: true ngay, 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ặc txt (đã 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).
  2. 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ặc verified: 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).
  3. 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/quote vớ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_expire dự kiến và enough — không trừ tiền, không giữ chỗ hay giữ giá.
  4. POST /waf/buy với {domain, backend_upstream, billing_cycle?, name?} và header Idempotency-Key ⇒ HTTP 200, provision_status: "ready", charged: true, order_code và 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ỏi info thưa thôi tới ready. Hạn của đơn tính từ lúc mua, kể cả khi còn provisioning.
  • 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, null nếu chưa cấp mã: gọi verify-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ới Idempotency-Key mớ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 theo msg).
  • 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ếu GET /waf/list hoặc liên hệ hỗ trợ; gửi lại cùng Idempotency-Key nhậ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_cycle bỏ 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ọi POST /waf/auto-renew với enabled: 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ử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). verify-domain khô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 ở logs và top_ips ở stats là 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_ips là 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ỉ.
  • Ẩ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ặc https:// + IP công khai hoặc tên miền + cổng (bỏ trống cổng = 80 với http · 443 với https; bỏ trống scheme = http). Đường dẫn / query không được giữ — hệ thống lưu dạng scheme://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-backend lạ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-backend vớ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_statusNghĩa (kèm order_status)
readyactive — 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.
provisioningactive — đã 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).
suspendedpending_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.
expiredexpired — 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ả list lẫn info) — 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_deadline mất renew + auto_renew; đơn đang rao bán trên chợ mất change_cycle + delete; đơn expired rỗ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ỏ; null khi đơ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ừ — 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) · billing_cycle · months · renew_auto · time_buy · time_expire. info thêm renew_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).
  • list trả 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/renew vớ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á: quote vớ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-After 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ừ (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ằng POST /waf/auto-renew với enabled là 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ới time_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_expire mà chưa gia hạn ⇒ ở lượt kiểm kế tiếp (mỗi 6 giờ) đơn chuyển pending_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ước renew_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_deadline không gia hạn được nữa (409 ORDER_EXPIRED) — ở lượt kiểm sau đó đơn chuyển expired: 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). Đơn expired bị xoá hẳn khỏi list 30 ngày sau time_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ới blocked: true) · url_path (tối đa 500 ký tự) · risk_level (1 thấp · 2 trung bình · 3 cao; 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 trang limit (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: false và ba số là null — không có nghĩa là không có truy cập. top_ips lấ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 = đúng 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) — 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ận 503 SERVICE_DISABLED (GET /services/status báo waf: false); mọi lệnh trên đơn đang có vẫn chạy bình thường.
  • Hết chỗ: products vẫn bày sản phẩm với in_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ền sandbox-….example, IP máy chủ bảo vệ + backend thuộc dải tài liệu 203.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 ⇒ 202 provisioning; info của mã ấy về ready sau khoảng 60 giây. Gia hạn đơn mẫu vừa tạo ⇒ 429 COOLDOWN như thật (mua xong không gia hạn trong ngày) · logs mẫu rỗng · stats mẫu là số giả. verify-domain chạy thử không cấp mã mới, không tra DNS. Với order_code thật, stats chạ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ó trong list.

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ệnhCách lệnh trước trên cùng WAF
Gia hạn1 phút (tính riêng)
Đổi backend1 phút (tính riêng)
Bật/tắt tự gia hạn5 giây (tính riêng)
Gia hạntố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.

HTTPcodeÝ nghĩaNê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.
GET

/waf/products

Chỉ đọc

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ỗ 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ộcMô tả
in_stock query không 1 = chỉ bày khi còn chỗ (bỏ trống / 0 = luôn bày)
Yêu cầu
curl 'https://cloudmoon.net/api/v1/waf/products' \
  -H 'X-API-Key: ak_...'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('GET', '/v1/waf/products');
print_r($kq);
Phản hồi
{
    "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
        }
    }
}
GET

/waf/price

Chỉ đọc

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ừ 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/price

Không có tham số — chỉ cần header X-API-Key.

Yêu cầu
curl 'https://cloudmoon.net/api/v1/waf/price' \
  -H 'X-API-Key: ak_...'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('GET', '/v1/waf/price');
print_r($kq);
Phản hồi
{
    "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
    }
}
POST

/waf/verify-domain

Toàn quyền

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, 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ộcMô 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).

Yêu cầu
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}'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// 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);
Thân yêu cầu
{
    "domain": "shop.congty.vn",
    "check": true
}
Phản hồi
{
    "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"
    }
}
POST

/waf/quote

Chỉ đọc

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/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ộcMô 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.

Yêu cầ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"}'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// 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);
Thân yêu cầu
{
    "domain": "shop.congty.vn",
    "backend_upstream": "http://1.2.3.4:80",
    "billing_cycle": "oneyear"
}
Phản hồi
{
    "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
    }
}
POST

/waf/buy

Toàn quyền

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ỏ 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ộcMô 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).

Yêu cầu
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"}'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// 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);
Thân yêu cầu
{
    "domain": "shop.congty.vn",
    "backend_upstream": "http://1.2.3.4:80",
    "billing_cycle": "onemonth"
}
Phản hồi
{
    "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."
    }
}
GET

/waf/list

Chỉ đọc

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ạ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ộcMô 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
Yêu cầu
curl 'https://cloudmoon.net/api/v1/waf/list' \
  -H 'X-API-Key: ak_...'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('GET', '/v1/waf/list');
print_r($kq);
Phản hồi
{
    "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
    }
}
GET

/waf/info

Chỉ đọc

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 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ộcMô 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.

Yêu cầu
curl 'https://cloudmoon.net/api/v1/waf/info?order_code=201026WAFA1B2C3D4E5F6' \
  -H 'X-API-Key: ak_...'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// 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);
Phản hồi
{
    "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"
        ]
    }
}
POST

/waf/renew

Toàn quyền

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 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ộcMô 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).

Yêu cầu
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"}'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// 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);
Thân yêu cầu
{
    "order_code": "201026WAFA1B2C3D4E5F6"
}
Phản hồi
{
    "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
    }
}
POST

/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ộcMô 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).

Yêu cầu
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}'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// 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);
Thân yêu cầu
{
    "order_code": "201026WAFA1B2C3D4E5F6",
    "enabled": false
}
Phản hồi
{
    "status": "success",
    "msg": "Đã tắt tự gia hạn",
    "data": {
        "order_code": "201026WAFA1B2C3D4E5F6",
        "renew_auto": "off"
    }
}
POST

/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ộcMô 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).

Yêu cầu
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"}'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// 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);
Thân yêu cầu
{
    "order_code": "201026WAFA1B2C3D4E5F6",
    "billing_cycle": "oneyear"
}
Phản hồi
{
    "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
    }
}
POST

/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ộcMô 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).

Yêu cầu
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"}'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// 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);
Thân yêu cầu
{
    "order_code": "201026WAFA1B2C3D4E5F6",
    "backend_upstream": "http://5.6.7.8:80"
}
Phản hồi
{
    "status": "success",
    "msg": "Đã cập nhật backend",
    "data": {
        "order_code": "201026WAFA1B2C3D4E5F6",
        "backend_upstream": "http://5.6.7.8:80",
        "applied": true
    }
}
POST

/waf/delete

Toàn quyền

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ệ đượ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ộcMô 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).

Yêu cầu
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"}'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// 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);
Thân yêu cầu
{
    "order_code": "201026WAFA1B2C3D4E5F6",
    "confirm": "201026WAFA1B2C3D4E5F6"
}
Phản hồi
{
    "status": "success",
    "msg": "Đã xoá WAF — không hoàn tiền",
    "data": {
        "order_code": "201026WAFA1B2C3D4E5F6",
        "order_status": "expired",
        "refunded": false
    }
}
GET

/waf/logs

Chỉ đọc

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 (đơ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ộcMô 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.

Yêu cầu
curl 'https://cloudmoon.net/api/v1/waf/logs' \
  -H 'X-API-Key: ak_...'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// cm_api(): xem mục "Client mẫu" ở trang Tổng quan
$kq = cm_api('GET', '/v1/waf/logs');
print_r($kq);
Phản hồi
{
    "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
    }
}
GET

/waf/stats

Chỉ đọc

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ặ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ộcMô 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.

Yêu cầu
curl 'https://cloudmoon.net/api/v1/waf/stats?order_code=201026WAFA1B2C3D4E5F6' \
  -H 'X-API-Key: ak_...'
Yêu cầu
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())
Yêu cầu
// 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());
Yêu cầu
// 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);
Phản hồi
{
    "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
    }
}
Zalo