Truy cập lập trình đến số ảo, đơn hàng và số dư tài khoản.
Khuyến nghị
⟩Bắt đầu với SDK chính thức
Dùng SDK TypeScript/JavaScript hoặc Python cho tích hợp mới. Cả hai SDK mặc định dùng API công khai /v2, giữ idempotency key qua các lần retry an toàn, cung cấp typed errors và giữ vòng đời OTP nhất quán.
Tạo đơn hàng bằng product_id cho một ô mức giá chính xác và ổn định, hoặc bằng catalog_product_id, operator_id tùy chọn, min_price/max_price và khóa idempotency để các lệnh gọi trả phí có định tuyến an toàn khi thử lại.
catalog_product_idmax_priceIdempotency-Key
02
Dùng OTP
Chờ OTP, gửi mã trong app đích, rồi gọi finish để đóng order.
waitForOtpwait_for_otpfinish
03
Chỉ resend khi cần
Sau khi resend, chờ mã mới bằng afterCode trong TypeScript hoặc after_code trong Python.
can_resendresend_available_at
import { SmscodeClient, OtpTimeoutError } from "@smscode/sdk";const client = new SmscodeClient({ token: process.env.SMSCODE_TOKEN! });let orderId: number | undefined;try { const created = await client.orders.create({ catalog_product_id: Number(process.env.SMSCODE_CATALOG_PRODUCT_ID), max_price: "0.50", quantity: 1, }); const order = created.orders[0]!; orderId = order.id; const first = await client.orders.waitForOtp(orderId, { timeoutMs: 120_000 }); console.log(first.otpCode); // Gửi mã này trong app đích. await client.orders.finish(orderId);} catch (err) { if (err instanceof OtpTimeoutError && orderId !== undefined) { const current = await client.orders.get(orderId); if (current.can_cancel) await client.orders.cancel(orderId); } throw err;}
import osfrom smscode import OtpTimeoutError, SmscodeClientwith SmscodeClient(token=os.environ["SMSCODE_TOKEN"]) as client: created = client.orders.create( catalog_product_id=int(os.environ["SMSCODE_CATALOG_PRODUCT_ID"]), max_price="0.50", quantity=1, ) order = created.orders[0] order_id = int(order["id"]) try: first = client.orders.wait_for_otp(order_id, timeout_ms=120_000) print(first.otp_code) # Gửi mã này trong app đích. client.orders.finish(order_id) except OtpTimeoutError: current = client.orders.get(order_id) if current["can_cancel"]: client.orders.cancel(order_id) raise
Dùng can_resend và resend_available_at cho timing resend. Timestamp resend cấp thấp là nội bộ và không phải field response công khai.
⟩Tong Quan
Tất cả trường tiền tệ trên API /v1 đều bằng IDR (Rupiah Indonesia), dưới dạng số nguyên — ví dụ "price": 15000 và "balance": 500000 nghĩa là Rp 15.000 và Rp 500.000. Để có bản chiếu USD-native của cùng một sổ cái, hãy chuyển sang API v2 bằng nút chuyển phiên bản ở trên.
⟩Xác thực
Tất cả yêu cầu API đều yêu cầu Bearer token. Tạo token từ Cài đặt tài khoản trong bảng điều khiển, sau đó đính kèm vào mỗi yêu cầu:
Authorization:Bearer YOUR_API_TOKEN
Yêu cầu không có token hợp lệ sẽ nhận phản hồi 401 UNAUTHORIZED.
⟩URL cơ sở
Tất cả đường dẫn endpoint bên dưới tương đối với:
https://api.smscode.gg/v1
⟩Định dạng phản hồi
Mọi phản hồi trả về JSON với cấu trúc nhất quán. Tất cả phản hồi bao gồm header x-request-id để gỡ lỗi.
Tất cả trường tiền tệ trên API /v1 đều bằng IDR (Rupiah Indonesia), dưới dạng số nguyên — ví dụ "price": 15000 và "balance": 500000 nghĩa là Rp 15.000 và Rp 500.000. Để có bản chiếu USD-native của cùng một sổ cái, hãy chuyển sang API v2 bằng nút chuyển phiên bản ở trên.
Trả về các nhà mạng có thể chọn cho một quốc gia + dịch vụ. Nếu cả nhà mạng thật và tồn kho Any đều khả dụng, phản hồi sẽ có một dòng Any với operator_id null; nếu không có sản phẩm theo nhà mạng, danh sách sẽ rỗng.
Tạo đơn hàng số ảo mới. Tự động trừ số dư. Hỗ trợ header Idempotency-Key tùy chọn để tránh tạo đơn trùng lặp khi thử lại do lỗi mạng.
Nội dung yêu cầu
Tên
Kiểu
Bắt buộc
Mô tả
product_id
integer
Không
ID sản phẩm của ô mức giá chính xác và ổn định để đặt trực tiếp. Chỉ gửi MỘT trong hai: giá trị này hoặc catalog_product_id, không gửi cả hai.
catalog_product_id
integer
Không
ID umbrella quốc gia+nền tảng cho đặt hàng có định tuyến. Máy chủ chọn một mức giá hiện tại phù hợp. Gửi giá trị này hoặc product_id.
operator_id
integer
Không
ID nhà mạng tùy chọn từ /catalog/operators. Chỉ hợp lệ với catalog_product_id; bỏ qua đối với Any.
min_price
integer
Không
Giá sàn tùy chọn. Số nguyên IDR. Chỉ hợp lệ với catalog_product_id.
max_price
integer
Không
Giá trần tùy chọn. Số nguyên IDR. Chỉ hợp lệ với catalog_product_id.
prefer_provider
string
Không
Mã nhà cung cấp tùy chọn được ưu tiên khi các ưu đãi ngang nhau.
policy
string
Không
Chính sách định tuyến tùy chọn, chỉ hợp lệ khi dùng catalog_product_id. Giá trị: cheapest (mặc định) chọn ưu đãi tốt có giá thấp nhất; best_success xếp hạng các ưu đãi theo tỷ lệ giao thành công gần đây trước. best_success chấm điểm mỗi nhà cung cấp theo tỷ lệ đơn nhận được OTP trong 30 ngày trọn vẹn gần nhất, theo dải 10%, và chỉ tính một nhà cung cấp khi họ có ít nhất 20 đơn trong khoảng đó — nhà cung cấp dưới ngưỡng này hoặc chưa có lịch sử được coi là trung tính, nên các ưu đãi mới không bao giờ bị bỏ rơi (tùy chọn; tín hiệu khởi đầu ở mức trung tính). Khi prefer_provider cũng được đặt, nhà cung cấp ưu tiên vẫn được xếp trước.
quantity
integer
Không
Số lượng (1-100, mặc định 1)
Truyền header Idempotency-Key để thử lại an toàn mà không tạo đơn trùng lặp. Key có thể chứa chữ cái, chữ số, dấu gạch ngang và gạch dưới (A-Z a-z 0-9 _ -), tối đa 128 ký tự; key không hợp lệ sẽ bị từ chối với 422 VALIDATION_ERROR. Thử lại với cùng key và cùng body sẽ phát lại kết quả ban đầu (bao gồm failed_count khi thành công một phần). Lần thử lại đã đến nhà cung cấp nhưng thất bại sẽ được ghi lại và phát lại đúng lỗi đó — hãy dùng key MỚI để thử lại. Lỗi không có tác dụng phụ (không đủ số dư, không có ưu đãi khả dụng) sẽ giải phóng key, nên bạn có thể nạp tiền và thử lại với cùng key. Dùng lại một key với body khác sẽ trả về 422 IDEMPOTENCY_KEY_REUSED, và yêu cầu vẫn đang xử lý với key đó sẽ trả về 409 REQUEST_IN_PROGRESS. Trường failed_reason trong phản hồi create luôn là null — nó chỉ được điền khi poll/liệt kê đơn hàng.
Ví dụ yêu cầu
curl -s -X POST https://api.smscode.gg/v1/orders/create \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: unique-request-id-123" \ -d '{"product_id":142,"quantity":1}'# Or route by catalog_product_id — the server picks a current tier.# product_id is the stable exact tier-slot id. catalog_product_id is the# country+platform umbrella for routed ordering. Optional min_price/max_price# bound the tier; operator_id scopes to a carrier from /catalog/operators.# Pass EITHER product_id OR catalog_product_id.curl -s -X POST https://api.smscode.gg/v1/orders/create \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: unique-request-id-124" \ -d '{"catalog_product_id":87,"min_price":12000,"max_price":20000,"operator_id":433}'
Kích hoạt lại một số đã hoàn tất — đặt lại chính số đó để nhận thêm một mã xác minh khác mà không cần thuê số mới. Chỉ đơn hàng đã hoàn tất có số hỗ trợ kích hoạt lại mới đủ điều kiện (kiểm tra can_reactivate trên đơn hàng, hoặc xem trước bằng reactivate-options). Đơn con được kích hoạt lại là một đơn hàng MỚI, được trả về theo cùng định dạng như create; số dư bị trừ tự động.
Nội dung yêu cầu
Tên
Kiểu
Bắt buộc
Mô tả
id
integer
Có
Đơn hàng đã hoàn tất cần kích hoạt lại.
max_price
integer
Không
Trần chi phí tùy chọn. Số nguyên IDR. Việc kích hoạt lại sẽ bị từ chối với 422 VALIDATION_ERROR nếu chi phí hiện tại vượt quá mức này.
Giống như create, đây là một thao tác thay đổi tiền — hãy truyền header Idempotency-Key để thử lại an toàn (một create và một reactivate không bao giờ xung đột trên cùng một key). Dùng lại một key với body khác sẽ trả về 422 IDEMPOTENCY_KEY_REUSED, và một yêu cầu vẫn đang xử lý với key đó sẽ trả về 409 REQUEST_IN_PROGRESS. Một số không thể kích hoạt lại sẽ trả về 409 CONFLICT; số dư quá thấp sẽ trả về 409 INSUFFICIENT_BALANCE.
Xem trước chi phí kích hoạt lại ngay lúc này. Chỉ đọc — không tiêu tốn Idempotency-Key nào và không tạo ra gì. Trả về chi phí dưới dạng số nguyên IDR. Chỉ khả dụng cho đơn hàng đã hoàn tất có số hỗ trợ kích hoạt lại.
Tham số đường dẫn
Tên
Kiểu
Bắt buộc
Mô tả
id
integer
Có
Mã đơn hàng cần xem trước chi phí kích hoạt lại (tham số đường dẫn).
Gửi sự kiện thử nghiệm đến URL webhook đã cấu hình. Trả về mã trạng thái HTTP từ máy chủ của bạn. Hữu ích để kiểm tra endpoint hoạt động trước khi vận hành chính thức.
Tham số
Không có
Ví dụ yêu cầu
curl -s -X POST https://api.smscode.gg/v1/webhook/test \ -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v1/webhook/test", { method: "POST", headers: { Authorization: "Bearer YOUR_API_TOKEN" },});const data = await res.json();
Cấu hình URL webhook để nhận thông báo đẩy theo thời gian thực cho các sự kiện đơn hàng thay vì polling. Đây là phương pháp được khuyến nghị cho bot script.
Sự kiện
Sự kiện
Kích hoạt
order.otp_received
Đã nhận SMS mới; mã phân tích có thể là null
order.completed
Đơn hàng đã hoàn thành (thủ công hoặc khi hết hạn)
order.expired
Đơn hàng hết hạn trước khi nhận SMS (đã hoàn tiền)
order.canceled
Đơn hàng bị hủy bởi người dùng (đã hoàn tiền)
Mỗi SMS mới phát ra event này. otp_code có thể là null khi otp_message hiện diện. Nhiều event SMS có thể đến không theo thứ tự; dùng sms_revision để bỏ qua cặp tổng hợp cũ hơn.
Xác minh chữ ký này trên máy chủ để đảm bảo yêu cầu là xác thực. Gửi theo kiểu fire-and-forget với timeout 3 giây và không thử lại.
⟩Giới hạn tốc độ
Yêu cầu API được giới hạn tốc độ theo nhóm endpoint. Vượt quá giới hạn trả về 429 Too Many Requests với header Retry-After cho biết số giây cần đợi.
Nhóm endpoint
Giới hạn
Cửa sổ
Danh mục (quốc gia, dịch vụ, sản phẩm, tỷ giá)
5.000 yêu cầu
60 giây
Số dư
600 yêu cầu
60 giây
Đọc đơn hàng (danh sách, chi tiết, hoạt động)
5.000 yêu cầu
60 giây
Tạo đơn hàng
3.000 yêu cầu
60 giây
Hủy đơn hàng
1.000 yêu cầu
60 giây
Thao tác đơn hàng (hoàn thành, gửi lại)
1.000 yêu cầu
60 giây
Cấu hình webhook (xem, cập nhật)
600 yêu cầu
60 giây
Thử webhook
10 yêu cầu
60 giây
⟩Mã lỗi
Phản hồi lỗi bao gồm một trong các mã sau trong error.code:
Mã
HTTP
Mô tả
UNAUTHORIZED
401
Thiếu hoặc API token không hợp lệ
FORBIDDEN
403
Truy cập bị từ chối
NOT_FOUND
404
Không tìm thấy tài nguyên (đơn hàng, tỷ giá, v.v.)
CONFLICT
409
Yêu cầu trùng lặp hoặc xung đột tài nguyên
INSUFFICIENT_BALANCE
409
Số dư không đủ để tạo đơn hàng
VALIDATION_ERROR
422
Tham số yêu cầu không hợp lệ
RATE_LIMIT_EXCEEDED
429
Quá nhiều yêu cầu (kiểm tra header Retry-After)
INTERNAL_ERROR
500
Lỗi máy chủ nội bộ
PROVIDER_ERROR
422
Nhà cung cấp SMS thượng nguồn từ chối yêu cầu. Khi tạo đơn thất bại, lỗi có thể kèm details: cause_counts (đơn dùng product_id cũ — bảng đếm nhóm theo nguyên nhân) hoặc attempts (đơn dùng catalog_product_id — kết quả từng lần thử), với các giá trị ok, no_numbers, insufficient_balance, price_rejected, provider_unavailable, provider_account_balance, provider_error.
NO_OFFER_AVAILABLE
422
Không có ưu đãi đang hoạt động nào khớp với sản phẩm và chính sách được yêu cầu (giới hạn giá, tình trạng còn hàng).
CANCEL_TOO_EARLY
409
Đơn hàng quá mới để hủy — hãy đợi 2 phút
REQUEST_IN_PROGRESS
409
Một yêu cầu tạo đơn với idempotency key này vẫn đang được xử lý
IDEMPOTENCY_KEY_REUSED
422
Idempotency key này đã được dùng với một body yêu cầu khác
SERVICE_UNAVAILABLE
503
Dịch vụ tạm thời không khả dụng (bảo trì)
⟩Tong Quan
Tất cả trường tiền tệ trên API /v2 đều bằng USD, được trả về dưới dạng đối tượng tiền tệ — { "amount": "0.92", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" }. amount là một chuỗi thập phân; canonical_amount là giá trị sổ cái IDR chính xác (dùng nó để đối soát). Tỷ giá USD/IDR rate được áp dụng được công bố một lần cho mỗi phản hồi trong meta.fx. v2 là bản chiếu USD tại thời điểm hiển thị trên cùng một sổ cái IDR như v1 — nó không bao giờ lưu trữ hay giao dịch USD.
Tất cả trường tiền tệ trên API /v2 đều bằng USD, được trả về dưới dạng đối tượng tiền tệ — { "amount": "0.92", "currency": "USD", "canonical_amount": 15000, "canonical_currency": "IDR" }. amount là một chuỗi thập phân; canonical_amount là giá trị sổ cái IDR chính xác (dùng nó để đối soát). Tỷ giá USD/IDR rate được áp dụng được công bố một lần cho mỗi phản hồi trong meta.fx. v2 là bản chiếu USD tại thời điểm hiển thị trên cùng một sổ cái IDR như v1 — nó không bao giờ lưu trữ hay giao dịch USD.
Giống hệt v1 — chỉ đường dẫn gốc thay đổi (/v1 → /v2).
GET/catalog/operators
Trả về các nhà mạng có thể chọn cho một quốc gia + dịch vụ. Nếu cả nhà mạng thật và tồn kho Any đều khả dụng, phản hồi sẽ có một dòng Any với operator_id null; nếu không có sản phẩm theo nhà mạng, danh sách sẽ rỗng.
v2: các trường tiền tệ là đối tượng tiền tệ USD và phản hồi mang theo một meta.fx { pair, rate, rate_as_of } duy nhất. rate là số IDR nguyên trên 1 USD, nên USD = canonical_amount / rate. Tổng dùng 2 chữ số thập phân; giá/hoàn tiền theo từng mục dùng 4. Một số tiền dương thực sự không bao giờ được làm tròn thành 0.00. rate_as_of là dấu thời gian RFC3339 của tỷ giá (dạng +00:00) hoặc null khi không có dấu thời gian được ghi lại.
Chỉ v2: nếu không có tỷ giá USD/IDR khả dụng, các endpoint tiền tệ trả về 503 FX_RATE_UNAVAILABLE kèm header Retry-After thay vì phần thân tiền tệ. v1 không bao giờ trả về điều này.
GET/catalog/exchange-rate
Trả về tỷ giá hối đoái USD/IDR hiện tại được dùng để chuyển đổi tiền tệ.
Tham số
Không có — v2 luôn trả về USD/IDR; tham số ?pair của v1 bị bỏ qua.
v2: trả về { pair, rate, rate_as_of } (không có base_currency/quote_currency, không có lớp bọc meta — tỷ giá chính là dữ liệu). ?pair bị bỏ qua — v2 luôn trả về USD/IDR (v1 tôn trọng ?pair). Trả về 503 FX_RATE_UNAVAILABLE nếu không có tỷ giá khả dụng.
GET/balance
Trả về số dư tài khoản của người dùng đã xác thực.
v2: các trường tiền tệ là đối tượng tiền tệ USD và phản hồi mang theo một meta.fx { pair, rate, rate_as_of } duy nhất. rate là số IDR nguyên trên 1 USD, nên USD = canonical_amount / rate. Tổng dùng 2 chữ số thập phân; giá/hoàn tiền theo từng mục dùng 4. Một số tiền dương thực sự không bao giờ được làm tròn thành 0.00. rate_as_of là dấu thời gian RFC3339 của tỷ giá (dạng +00:00) hoặc null khi không có dấu thời gian được ghi lại.
Chỉ v2: nếu không có tỷ giá USD/IDR khả dụng, các endpoint tiền tệ trả về 503 FX_RATE_UNAVAILABLE kèm header Retry-After thay vì phần thân tiền tệ. v1 không bao giờ trả về điều này.
GET/orders
Trả về danh sách đơn hàng của người dùng đã xác thực, sắp xếp theo mới nhất. Hỗ trợ lọc theo trạng thái và phân trang qua offset.
Tham số truy vấn
Tên
Kiểu
Bắt buộc
Mô tả
limit
integer
Không
Số kết quả tối đa (1-100, mặc định 20)
offset
integer
Không
Số kết quả bỏ qua (mặc định 0)
status
string
Không
Lọc theo trạng thái: ACTIVE, OTP_RECEIVED, COMPLETED, CANCELED, EXPIRED (không phân biệt hoa thường)
v2: các trường tiền tệ là đối tượng tiền tệ USD và phản hồi mang theo một meta.fx { pair, rate, rate_as_of } duy nhất. rate là số IDR nguyên trên 1 USD, nên USD = canonical_amount / rate. Tổng dùng 2 chữ số thập phân; giá/hoàn tiền theo từng mục dùng 4. Một số tiền dương thực sự không bao giờ được làm tròn thành 0.00. rate_as_of là dấu thời gian RFC3339 của tỷ giá (dạng +00:00) hoặc null khi không có dấu thời gian được ghi lại.
Chỉ v2: nếu không có tỷ giá USD/IDR khả dụng, các endpoint tiền tệ trả về 503 FX_RATE_UNAVAILABLE kèm header Retry-After thay vì phần thân tiền tệ. v1 không bao giờ trả về điều này.
GET/orders/{id}
Trả về một đơn hàng theo ID. Chỉ trả về đơn hàng của người dùng đã xác thực.
v2: các trường tiền tệ là đối tượng tiền tệ USD và phản hồi mang theo một meta.fx { pair, rate, rate_as_of } duy nhất. rate là số IDR nguyên trên 1 USD, nên USD = canonical_amount / rate. Tổng dùng 2 chữ số thập phân; giá/hoàn tiền theo từng mục dùng 4. Một số tiền dương thực sự không bao giờ được làm tròn thành 0.00. rate_as_of là dấu thời gian RFC3339 của tỷ giá (dạng +00:00) hoặc null khi không có dấu thời gian được ghi lại.
Chỉ v2: nếu không có tỷ giá USD/IDR khả dụng, các endpoint tiền tệ trả về 503 FX_RATE_UNAVAILABLE kèm header Retry-After thay vì phần thân tiền tệ. v1 không bao giờ trả về điều này.
GET/orders/active
Liệt kê tất cả đơn hàng đang hoạt động (ACTIVE + OTP_RECEIVED). Sử dụng để theo dõi cập nhật trạng thái OTP.
v2: endpoint này không mang tiền tệ — nó không trả về amount cũng không trả về meta.fx (cùng cấu trúc như v1, dưới /v2).
POST/orders/create
Tạo đơn hàng số ảo mới. Tự động trừ số dư. Hỗ trợ header Idempotency-Key tùy chọn để tránh tạo đơn trùng lặp khi thử lại do lỗi mạng.
Nội dung yêu cầu
Tên
Kiểu
Bắt buộc
Mô tả
product_id
integer
Không
ID sản phẩm của ô mức giá chính xác và ổn định để đặt trực tiếp. Chỉ gửi MỘT trong hai: giá trị này hoặc catalog_product_id, không gửi cả hai.
catalog_product_id
integer
Không
ID umbrella quốc gia+nền tảng cho đặt hàng có định tuyến. Máy chủ chọn một mức giá hiện tại phù hợp. Gửi giá trị này hoặc product_id.
operator_id
integer
Không
ID nhà mạng tùy chọn từ /catalog/operators. Chỉ hợp lệ với catalog_product_id; bỏ qua đối với Any.
min_price
string
Không
Giá sàn tùy chọn. Chuỗi thập phân USD (ví dụ "0.30"). Chỉ hợp lệ với catalog_product_id.
max_price
string
Không
Giá trần tùy chọn. Chuỗi thập phân USD (ví dụ "0.50"). Chỉ hợp lệ với catalog_product_id.
prefer_provider
string
Không
Mã nhà cung cấp tùy chọn được ưu tiên khi các ưu đãi ngang nhau.
policy
string
Không
Chính sách định tuyến tùy chọn, chỉ hợp lệ khi dùng catalog_product_id. Giá trị: cheapest (mặc định) chọn ưu đãi tốt có giá thấp nhất; best_success xếp hạng các ưu đãi theo tỷ lệ giao thành công gần đây trước. best_success chấm điểm mỗi nhà cung cấp theo tỷ lệ đơn nhận được OTP trong 30 ngày trọn vẹn gần nhất, theo dải 10%, và chỉ tính một nhà cung cấp khi họ có ít nhất 20 đơn trong khoảng đó — nhà cung cấp dưới ngưỡng này hoặc chưa có lịch sử được coi là trung tính, nên các ưu đãi mới không bao giờ bị bỏ rơi (tùy chọn; tín hiệu khởi đầu ở mức trung tính). Khi prefer_provider cũng được đặt, nhà cung cấp ưu tiên vẫn được xếp trước.
quantity
integer
Không
Số lượng (1-100, mặc định 1)
Truyền header Idempotency-Key để thử lại an toàn mà không tạo đơn trùng lặp. Key có thể chứa chữ cái, chữ số, dấu gạch ngang và gạch dưới (A-Z a-z 0-9 _ -), tối đa 128 ký tự; key không hợp lệ sẽ bị từ chối với 422 VALIDATION_ERROR. Thử lại với cùng key và cùng body sẽ phát lại kết quả ban đầu (bao gồm failed_count khi thành công một phần). Lần thử lại đã đến nhà cung cấp nhưng thất bại sẽ được ghi lại và phát lại đúng lỗi đó — hãy dùng key MỚI để thử lại. Lỗi không có tác dụng phụ (không đủ số dư, không có ưu đãi khả dụng) sẽ giải phóng key, nên bạn có thể nạp tiền và thử lại với cùng key. Dùng lại một key với body khác sẽ trả về 422 IDEMPOTENCY_KEY_REUSED, và yêu cầu vẫn đang xử lý với key đó sẽ trả về 409 REQUEST_IN_PROGRESS. Trường failed_reason trong phản hồi create luôn là null — nó chỉ được điền khi poll/liệt kê đơn hàng.
v2: các trường tiền tệ là đối tượng tiền tệ USD và phản hồi mang theo một meta.fx { pair, rate, rate_as_of } duy nhất. rate là số IDR nguyên trên 1 USD, nên USD = canonical_amount / rate. Tổng dùng 2 chữ số thập phân; giá/hoàn tiền theo từng mục dùng 4. Một số tiền dương thực sự không bao giờ được làm tròn thành 0.00. rate_as_of là dấu thời gian RFC3339 của tỷ giá (dạng +00:00) hoặc null khi không có dấu thời gian được ghi lại.
Chỉ v2: nếu không có tỷ giá USD/IDR khả dụng, các endpoint tiền tệ trả về 503 FX_RATE_UNAVAILABLE kèm header Retry-After thay vì phần thân tiền tệ. v1 không bao giờ trả về điều này.
POST/orders/cancel
Hủy đơn hàng đang hoạt động. Phí thuê sẽ được hoàn vào số dư tài khoản.
v2: các trường tiền tệ là đối tượng tiền tệ USD và phản hồi mang theo một meta.fx { pair, rate, rate_as_of } duy nhất. rate là số IDR nguyên trên 1 USD, nên USD = canonical_amount / rate. Tổng dùng 2 chữ số thập phân; giá/hoàn tiền theo từng mục dùng 4. Một số tiền dương thực sự không bao giờ được làm tròn thành 0.00. rate_as_of là dấu thời gian RFC3339 của tỷ giá (dạng +00:00) hoặc null khi không có dấu thời gian được ghi lại.
Chỉ v2: nếu không có tỷ giá USD/IDR khả dụng, các endpoint tiền tệ trả về 503 FX_RATE_UNAVAILABLE kèm header Retry-After thay vì phần thân tiền tệ. v1 không bao giờ trả về điều này.
POST/orders/finish
Đánh dấu đơn hàng đã hoàn thành sau khi nhận OTP. Giải phóng số ngay lập tức thay vì đợi hết hạn.
Giống hệt v1 — chỉ đường dẫn gốc thay đổi (/v1 → /v2).
POST/orders/reactivate
Kích hoạt lại một số đã hoàn tất — đặt lại chính số đó để nhận thêm một mã xác minh khác mà không cần thuê số mới. Chỉ đơn hàng đã hoàn tất có số hỗ trợ kích hoạt lại mới đủ điều kiện (kiểm tra can_reactivate trên đơn hàng, hoặc xem trước bằng reactivate-options). Đơn con được kích hoạt lại là một đơn hàng MỚI, được trả về theo cùng định dạng như create; số dư bị trừ tự động.
Nội dung yêu cầu
Tên
Kiểu
Bắt buộc
Mô tả
id
integer
Có
Đơn hàng đã hoàn tất cần kích hoạt lại.
max_price
string
Không
Trần chi phí tùy chọn. Chuỗi thập phân USD (ví dụ "0.50"). Việc kích hoạt lại sẽ bị từ chối với 422 VALIDATION_ERROR nếu chi phí hiện tại vượt quá mức này.
Giống như create, đây là một thao tác thay đổi tiền — hãy truyền header Idempotency-Key để thử lại an toàn (một create và một reactivate không bao giờ xung đột trên cùng một key). Dùng lại một key với body khác sẽ trả về 422 IDEMPOTENCY_KEY_REUSED, và một yêu cầu vẫn đang xử lý với key đó sẽ trả về 409 REQUEST_IN_PROGRESS. Một số không thể kích hoạt lại sẽ trả về 409 CONFLICT; số dư quá thấp sẽ trả về 409 INSUFFICIENT_BALANCE.
v2: các trường tiền tệ là đối tượng tiền tệ USD và phản hồi mang theo một meta.fx { pair, rate, rate_as_of } duy nhất. rate là số IDR nguyên trên 1 USD, nên USD = canonical_amount / rate. Tổng dùng 2 chữ số thập phân; giá/hoàn tiền theo từng mục dùng 4. Một số tiền dương thực sự không bao giờ được làm tròn thành 0.00. rate_as_of là dấu thời gian RFC3339 của tỷ giá (dạng +00:00) hoặc null khi không có dấu thời gian được ghi lại.
Chỉ v2: nếu không có tỷ giá USD/IDR khả dụng, các endpoint tiền tệ trả về 503 FX_RATE_UNAVAILABLE kèm header Retry-After thay vì phần thân tiền tệ. v1 không bao giờ trả về điều này.
GET/orders/{id}/reactivate-options
Xem trước chi phí kích hoạt lại ngay lúc này. Chỉ đọc — không tiêu tốn Idempotency-Key nào và không tạo ra gì. Trả về chi phí dưới dạng đối tượng tiền tệ USD kèm biên nhận FX. Chỉ khả dụng cho đơn hàng đã hoàn tất có số hỗ trợ kích hoạt lại.
Tham số đường dẫn
Tên
Kiểu
Bắt buộc
Mô tả
id
integer
Có
Mã đơn hàng cần xem trước chi phí kích hoạt lại (tham số đường dẫn).
v2: các trường tiền tệ là đối tượng tiền tệ USD và phản hồi mang theo một meta.fx { pair, rate, rate_as_of } duy nhất. rate là số IDR nguyên trên 1 USD, nên USD = canonical_amount / rate. Tổng dùng 2 chữ số thập phân; giá/hoàn tiền theo từng mục dùng 4. Một số tiền dương thực sự không bao giờ được làm tròn thành 0.00. rate_as_of là dấu thời gian RFC3339 của tỷ giá (dạng +00:00) hoặc null khi không có dấu thời gian được ghi lại.
Chỉ v2: nếu không có tỷ giá USD/IDR khả dụng, các endpoint tiền tệ trả về 503 FX_RATE_UNAVAILABLE kèm header Retry-After thay vì phần thân tiền tệ. v1 không bao giờ trả về điều này.
GET/webhook
Trả về cấu hình webhook notification hiện tại của bạn.
Giống hệt v1 — chỉ đường dẫn gốc thay đổi (/v1 → /v2).
POST/webhook/test
Gửi sự kiện thử nghiệm đến URL webhook đã cấu hình. Trả về mã trạng thái HTTP từ máy chủ của bạn. Hữu ích để kiểm tra endpoint hoạt động trước khi vận hành chính thức.
Tham số
Không có
Ví dụ yêu cầu
curl -s -X POST https://api.smscode.gg/v2/webhook/test \ -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v2/webhook/test", { method: "POST", headers: { Authorization: "Bearer YOUR_API_TOKEN" },});const data = await res.json();
Giống hệt v1 — chỉ đường dẫn gốc thay đổi (/v1 → /v2).
⟩Thông báo Webhook
Cấu hình URL webhook để nhận thông báo đẩy theo thời gian thực cho các sự kiện đơn hàng thay vì polling. Đây là phương pháp được khuyến nghị cho bot script.
Sự kiện
Sự kiện
Kích hoạt
order.otp_received
Đã nhận SMS mới; mã phân tích có thể là null
order.completed
Đơn hàng đã hoàn thành (thủ công hoặc khi hết hạn)
order.expired
Đơn hàng hết hạn trước khi nhận SMS (đã hoàn tiền)
order.canceled
Đơn hàng bị hủy bởi người dùng (đã hoàn tiền)
Mỗi SMS mới phát ra event này. otp_code có thể là null khi otp_message hiện diện. Nhiều event SMS có thể đến không theo thứ tự; dùng sms_revision để bỏ qua cặp tổng hợp cũ hơn.
Xác minh chữ ký này trên máy chủ để đảm bảo yêu cầu là xác thực. Gửi theo kiểu fire-and-forget với timeout 3 giây và không thử lại.
⟩Giới hạn tốc độ
Yêu cầu API được giới hạn tốc độ theo nhóm endpoint. Vượt quá giới hạn trả về 429 Too Many Requests với header Retry-After cho biết số giây cần đợi.
Nhóm endpoint
Giới hạn
Cửa sổ
Danh mục (quốc gia, dịch vụ, sản phẩm, tỷ giá)
5.000 yêu cầu
60 giây
Số dư
600 yêu cầu
60 giây
Đọc đơn hàng (danh sách, chi tiết, hoạt động)
5.000 yêu cầu
60 giây
Tạo đơn hàng
3.000 yêu cầu
60 giây
Hủy đơn hàng
1.000 yêu cầu
60 giây
Thao tác đơn hàng (hoàn thành, gửi lại)
1.000 yêu cầu
60 giây
Cấu hình webhook (xem, cập nhật)
600 yêu cầu
60 giây
Thử webhook
10 yêu cầu
60 giây
⟩Mã lỗi
Phản hồi lỗi bao gồm một trong các mã sau trong error.code:
Mã
HTTP
Mô tả
UNAUTHORIZED
401
Thiếu hoặc API token không hợp lệ
FORBIDDEN
403
Truy cập bị từ chối
NOT_FOUND
404
Không tìm thấy tài nguyên (đơn hàng, tỷ giá, v.v.)
CONFLICT
409
Yêu cầu trùng lặp hoặc xung đột tài nguyên
INSUFFICIENT_BALANCE
409
Số dư không đủ để tạo đơn hàng
VALIDATION_ERROR
422
Tham số yêu cầu không hợp lệ
RATE_LIMIT_EXCEEDED
429
Quá nhiều yêu cầu (kiểm tra header Retry-After)
INTERNAL_ERROR
500
Lỗi máy chủ nội bộ
PROVIDER_ERROR
422
Nhà cung cấp SMS thượng nguồn từ chối yêu cầu. Khi tạo đơn thất bại, lỗi có thể kèm details: cause_counts (đơn dùng product_id cũ — bảng đếm nhóm theo nguyên nhân) hoặc attempts (đơn dùng catalog_product_id — kết quả từng lần thử), với các giá trị ok, no_numbers, insufficient_balance, price_rejected, provider_unavailable, provider_account_balance, provider_error.
NO_OFFER_AVAILABLE
422
Không có ưu đãi đang hoạt động nào khớp với sản phẩm và chính sách được yêu cầu (giới hạn giá, tình trạng còn hàng).
CANCEL_TOO_EARLY
409
Đơn hàng quá mới để hủy — hãy đợi 2 phút
REQUEST_IN_PROGRESS
409
Một yêu cầu tạo đơn với idempotency key này vẫn đang được xử lý
IDEMPOTENCY_KEY_REUSED
422
Idempotency key này đã được dùng với một body yêu cầu khác
SERVICE_UNAVAILABLE
503
Dịch vụ tạm thời không khả dụng (bảo trì)
FX_RATE_UNAVAILABLE
503
Tỷ giá hối đoái USD/IDR không khả dụng (các endpoint tiền tệ v2) — trả về 503 kèm header Retry-After.
v1 → v2
⟩Chuyển từ v1 sang v2
v1 phục vụ IDR; v2 phục vụ USD. Cả hai phiên bản cùng tồn tại vĩnh viễn — không có việc ngừng hỗ trợ. Chọn một phiên bản cho mỗi tích hợp; đừng trộn lẫn đường dẫn gốc. v2 giống hệt v1 ngoại trừ cách biểu diễn tiền tệ.
Khía cạnh
v1 · IDR
v2 · USD
Trường tiền tệ
IDR nguyên, vd. 15000
Đối tượng tiền tệ { amount, currency, canonical_amount, canonical_currency }
meta.fx
Không có
Bắt buộc trên mọi phản hồi mang tiền tệ
Tiền tệ
IDR
USD (cố định trong mã)
FX_RATE_UNAVAILABLE
—
503 + Retry-After mới khi không có tỷ giá khả dụng
Độ chính xác
—
Tổng 2 chữ số, giá/hoàn tiền 4 chữ số, làm tròn lên với số dương
product_id là ID ô mức giá SMSCode ổn định. Hãy lưu nó khi bạn muốn đặt đúng mức giá đó; giá và độ khả dụng có thể thay đổi ngay trên cùng một dòng. catalog_product_id là umbrella quốc gia+nền tảng ổn định cho đặt hàng có định tuyến; dùng với operator_id, min_price, max_price, prefer_provider và policy tùy chọn khi bạn muốn máy chủ chọn một mức giá hiện tại phù hợp.
Phân tích các trường tiền tệ dưới dạng đối tượng — đọc amount như một chuỗi thập phân; currency là "USD".
Để đối soát sổ cái, dùng canonical_amount (IDR chính xác); số tiền USD amount là bản chiếu tại thời điểm hiển thị và rate được công bố một lần trong meta.fx.
Xử lý FX_RATE_UNAVAILABLE (503) mới — thử lại sau Retry-After. v1 không bao giờ trả về điều này.