RelySMS
API · giao thức handler_api.php

Số nhận SMS — ngay trong phần mềm của bạn

Nếu phần mềm của bạn đã chạy với một dịch vụ kích hoạt qua handler_api.php, nó sẽ chạy với RelySMS: chỉ cần đổi địa chỉ máy chủ và khóa. Cùng thao tác, cùng phản hồi, theo giá và chính sách hoàn tiền của chúng tôi.

https://relysms.pro/stubs/handler_api.php

Bắt đầu nhanh

  1. Đăng nhập và mở Số dư → API → Tạo khóa. Khóa chỉ hiển thị một lần — hãy lưu lại.
  2. Nạp số dư từ $20 trở lên: chỉ với số dư này mới mua được qua API. Giữ khóa khi số dư bằng 0 vẫn được.
  3. Trong phần mềm, đặt máy chủ là https://relysms.pro/stubs/handler_api.php và dùng khóa của bạn thay cho khóa của dịch vụ cũ.
  4. Mua số (getNumber), rồi hỏi trạng thái mỗi 5–10 giây (getStatus) cho đến khi nhận STATUS_OK kèm mã.
  5. Hoàn tất đơn (setStatus=6). Nếu không có mã, hủy sau 2 phút (setStatus=8) hoặc chờ hết thời gian: tiền tự hoàn lại.

Quy tắc và giới hạn

  • Mua qua API cần số dư tối thiểu $20. Dưới mức đó, getNumber trả NO_BALANCE; các phương thức khác vẫn hoạt động.
  • Số là của bạn trong 20 phút. Không có mã — đơn tự đóng và tiền về lại số dư.
  • Có thể hủy sau 2 phút kể từ lúc mua nếu chưa có mã. Tiền về ngay.
  • Khi mã đầu tiên đến, đơn được tính là đã trả và không hoàn lại. Trong thời gian còn mở, các mã tiếp theo vẫn có thể đến.
  • Tối đa 20 yêu cầu và 5 lượt mua mỗi giây cho một khóa; tối đa 50 đơn đang mở cùng lúc.
  • Giá được chốt lúc mua. maxPrice giúp không mua quá giới hạn của bạn.
  • Áp dụng điều khoản dịch vụ: cấm spam, lừa đảo và đăng ký hàng loạt vì các mục đích đó.

Phương thức

Mọi yêu cầu là GET hoặc POST tới một địa chỉ, tham số nằm trong query string hoặc form. Khóa gửi trong api_key, thao tác trong action.

getBalance

Số dư tài khoản tính bằng đô la.

Chỉ api_key và action.

GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getBalance

Phản hồi

ACCESS_BALANCE:25.00

getNumber

Mua số cho một dịch vụ ở một quốc gia. Trừ tiền ngay; hoàn lại nếu không có mã. Phản hồi: ACCESS_NUMBER:mã_đơn:số_điện_thoại.

Tham sốBắt buộcMô tả
servicecóMã dịch vụ (getServicesList), ví dụ tg.
countrycóMã quốc gia (getCountries).
maxPricekhôngGiá tối đa bằng đô la. Đắt hơn — WRONG_MAX_PRICE kèm giá hiện tại, không trừ tiền.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getNumber&service=tg&country=187&maxPrice=0.80

Phản hồi

ACCESS_NUMBER:1042:15550001111

Lỗi có thể gặp: BAD_SERVICE, BAD_COUNTRY, NO_NUMBERS, NO_BALANCE, WRONG_MAX_PRICE:0.59, LIMIT_ACTIVATIONS, RATE_LIMIT, BANNED

getNumberV2

Giống getNumber, nhưng trả JSON gồm giá và thời gian mở.

Tham sốBắt buộcMô tả
servicecóMã dịch vụ.
countrycóMã quốc gia.
maxPricekhôngGiá tối đa bằng đô la.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getNumberV2&service=tg&country=187&maxPrice=0.80

Phản hồi

{
  "activationId": 1042,
  "phoneNumber": "15550001111",
  "activationCost": 0.59,
  "countryCode": "187",
  "canGetAnotherSms": true,
  "activationTime": "2026-10-27T10:00:00.000Z",
  "activationEndTime": "2026-10-27T10:20:00.000Z"
}

Lỗi có thể gặp: BAD_SERVICE, BAD_COUNTRY, NO_NUMBERS, NO_BALANCE, WRONG_MAX_PRICE:0.59, LIMIT_ACTIVATIONS, RATE_LIMIT

getStatus

Trạng thái đơn: chờ mã, đã có mã (kèm mã) hoặc đã hủy.

Tham sốBắt buộcMô tả
idcóMã đơn từ getNumber.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getStatus&id=1042

Phản hồi

STATUS_OK:48213

Lỗi có thể gặp: NO_ACTIVATION

setStatus

Thao tác với đơn: sẵn sàng, mã khác, hoàn tất, hủy (xem Trạng thái).

Tham sốBắt buộcMô tả
idcóMã đơn.
statuscó1, 3, 6 hoặc 8.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=setStatus&id=1042&status=6

Phản hồi

ACCESS_ACTIVATION

Lỗi có thể gặp: NO_ACTIVATION, BAD_STATUS, EARLY_CANCEL_DENIED, ERROR_SQL

getActiveActivations

Mọi đơn đang mở của khóa: số, trạng thái, mã và nội dung đã nhận.

Chỉ api_key và action.

GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getActiveActivations

Phản hồi

{
  "status": "success",
  "activeActivations": [
    {
      "activationId": 1042,
      "serviceCode": "tg",
      "phoneNumber": "15550001111",
      "activationCost": 0.59,
      "activationStatus": "2",
      "smsCode": ["48213"],
      "smsText": ["Telegram code: 48213"],
      "activationTime": "2026-10-27T10:00:00.000Z",
      "countryCode": "187"
    }
  ]
}

getPrices

Giá của chúng tôi bằng đô la và số lượng số ước tính. Không tham số — mọi thứ đang bán.

Tham sốBắt buộcMô tả
servicekhôngChỉ dịch vụ này.
countrykhôngChỉ quốc gia này.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getPrices&service=tg&country=187

Phản hồi

{ "187": { "tg": { "cost": 0.59, "count": 1000 } } }

Lỗi có thể gặp: BAD_SERVICE, BAD_COUNTRY

getCountries

Danh sách quốc gia với mã giao thức và tên tiếng Nga, tiếng Anh.

Chỉ api_key và action.

GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getCountries

Phản hồi

{ "187": { "id": 187, "rus": "США", "eng": "United States", "visible": 1 } }

getServicesList

Danh sách dịch vụ với mã giao thức.

Chỉ api_key và action.

GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getServicesList

Phản hồi

{ "status": "success", "services": [{ "code": "tg", "name": "Telegram" }] }

Trạng thái

Giá trị status trong setStatus:

  • status=1 → ACCESS_READY — Đã nhập số vào dịch vụ, đang chờ mã. Không thay đổi gì; giữ để tương thích.
  • status=3 → ACCESS_RETRY_GET — Yêu cầu thêm một mã cho cùng số — sau mã đầu tiên, khi đơn còn mở. Miễn phí. Cho đến khi mã mới đến, getStatus trả về STATUS_WAIT_RETRY.
  • status=6 → ACCESS_ACTIVATION — Hoàn tất đơn sau khi có mã. Số sẽ không nhận thêm SMS.
  • status=8 → ACCESS_CANCEL — Hủy đơn chưa có mã (sớm nhất sau 2 phút). Tiền về lại số dư.

Phản hồi của getStatus:

  • STATUS_WAIT_CODE — Chưa có mã — hỏi lại sau 5–10 giây.
  • STATUS_OK:48213 — Đã có mã; sau dấu hai chấm là mã (hoặc nội dung SMS nếu không chứa mã).
  • STATUS_WAIT_RETRY:48213 — Đã yêu cầu thêm mã nhưng chưa đến; sau dấu hai chấm là mã trước đó.
  • STATUS_CANCEL — Đã hủy hoặc đóng khi chưa có mã; tiền đã về số dư.

Lỗi

Lỗi trả về dạng chuỗi, như thông lệ của giao thức này. Tất cả, trừ RATE_LIMIT, đều có mã trạng thái 200.

NO_KEYThiếu api_key.
BAD_KEYKhóa sai, đã tắt, hoặc tài khoản bị khóa.
BAD_ACTIONThao tác không xác định.
BAD_SERVICEKhông có mã dịch vụ này.
BAD_COUNTRYKhông có mã quốc gia này.
NO_NUMBERSHiện không có số cho cặp này; không trừ tiền.
NO_BALANCESố dư dưới $20 (ngưỡng API) hoặc thấp hơn giá số.
WRONG_MAX_PRICEGiá vượt maxPrice; sau dấu hai chấm là giá hiện tại.
LIMIT_ACTIVATIONSQuá nhiều đơn đang mở — hãy hoàn tất hoặc hủy bớt.
RATE_LIMITQuá thường xuyên; HTTP 429. Thử lại sau một giây.
BANNEDTài khoản bị khóa — hãy liên hệ hỗ trợ.
NO_ACTIVATIONKhông có đơn với mã này cho khóa này.
BAD_STATUSThao tác này hiện không áp dụng cho đơn (ví dụ hoàn tất khi chưa có mã).
EARLY_CANCEL_DENIEDChỉ hủy được sau 2 phút kể từ lúc mua.
ERROR_SQLLỗi tạm thời phía chúng tôi — hãy gửi lại sau một phút.

Mã dịch vụ và quốc gia

Các mã là mã chuẩn của giao thức: tg — Telegram, wa — WhatsApp, v.v.; quốc gia 187 — Mỹ. getServicesList và getCountries trả danh sách đầy đủ — hãy lấy mã từ đó, không dùng bảng cũ: dịch vụ và quốc gia thay đổi theo hàng có sẵn.

REST API v1

Cùng số và cùng quy tắc như handler_api.php, nhưng dạng JSON: dịch vụ theo tên (telegram), quốc gia theo mã ISO (US), mã trạng thái HTTP và mã lỗi để chương trình dễ rẽ nhánh. Dùng cho mã mới; phần mềm đã dùng handler_api.php thì cứ giữ nguyên.

https://relysms.pro/api/v1

Khóa

Gửi khóa trong header: Authorization: Bearer <khóa> (hoặc X-Api-Key: <khóa>). Không đặt trong URL — URL bị ghi vào log. Giới hạn, ngưỡng $20 và danh mục giống handler_api.php.

Thử lại mà không mua trùng

Thêm header Idempotency-Key với giá trị của bạn (UUID, tối đa 255 ký tự) vào POST /orders và /orders/batch. Nếu mất kết nối và bạn gửi lại với cùng khóa, bạn nhận lại phản hồi đầu tiên (kèm header Idempotent-Replayed: true) và không có gì bị mua hai lần. Cùng khóa nhưng nội dung khác sẽ bị từ chối; yêu cầu lặp đến khi yêu cầu đầu còn đang chạy sẽ nhận idempotency_in_progress. Phản hồi thành công được giữ 24 giờ; lượt mua thất bại không trừ tiền và có thể gửi lại với cùng khóa.

Nhiều số cùng lúc

POST /orders/batch mua tối đa 20 số cho một dịch vụ và quốc gia trong một yêu cầu — đây là cách mua nhanh hơn 5 số mỗi giây. Các lượt mua diễn ra lần lượt; lượt đầu tiên thất bại sẽ dừng cả lô, phản hồi liệt kê những gì đã mua và lý do trong stoppedBy. Nếu không mua được gì, phản hồi chính là lỗi đó.

Phân trang

GET /orders trả đơn mới nhất trước. Khi next khác null, gửi nó làm before để lấy trang tiếp theo.

Webhook

Thay vì hỏi GET /orders/{id} liên tục, hãy đặt một địa chỉ HTTPS qua PUT /webhook và chúng tôi sẽ gửi POST tới đó khi đơn mua qua API có thay đổi. Nội dung là đơn hàng tại thời điểm gửi. Hãy trả lời bất kỳ mã 2xx nào trong 10 giây; một đơn có thể sinh nhiều sự kiện và cùng một sự kiện có thể đến hai lần sau khi thử lại, nên hãy dựa vào id lần gửi.

  • order.code_received — Có mã (mỗi mã mới lại gửi sự kiện này).
  • order.finished — Đơn đã hoàn tất — do bạn, hoặc khi hết thời gian sau khi có mã.
  • order.cancelled — Đã hủy khi chưa có mã; tiền đã về số dư.
  • order.expired — Hết thời gian mà không có mã; tiền đã về số dư.
  • ping — Thử nghiệm từ POST /webhook/test; order là null.
POST /relysms-hook HTTP/1.1
Content-Type: application/json
X-RelySMS-Event: order.code_received
X-RelySMS-Delivery: cm…
X-RelySMS-Signature: t=1793095272,v1=5f2b…

{
  "id": "cm…",
  "event": "order.code_received",
  "createdAt": "2026-10-27T10:01:12.000Z",
  "order": { "id": 1042, "status": "received", "codes": [{ "code": "48213", … }], … }
}

Mỗi yêu cầu có X-RelySMS-Signature: t=<thời gian unix>,v1=<chữ ký>. Chữ ký là HMAC-SHA256 của chuỗi "t.body" (body gốc, từng byte) với secret webhook của bạn, dạng hex. Hãy kiểm tra chữ ký và t không quá 5 phút trước khi tin nội dung.

Python

import hashlib, hmac, time

def verify(secret: str, body: bytes, header: str, tolerance=300) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    t, sig = parts.get("t", ""), parts.get("v1", "")
    if not t.isdigit() or abs(time.time() - int(t)) > tolerance:
        return False
    expected = hmac.new(secret.encode(), f"{t}.".encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, sig)

Node.js

import { createHmac, timingSafeEqual } from "node:crypto";

export function verify(secret, rawBody, header, tolerance = 300) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=", 2)));
  const t = Number(parts.t);
  if (!Number.isInteger(t) || Math.abs(Date.now() / 1000 - t) > tolerance) return false;
  const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return expected.length === parts.v1?.length && timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}

Nếu máy chủ của bạn không trả 2xx, chúng tôi thử lại sau 10 giây, 1 phút, 5 phút, 30 phút, 2 giờ và 6 giờ — tổng cộng 7 lần — rồi dừng. GET /webhook/deliveries cho thấy những gì đã gửi và đã lỗi.

Endpoint

GET /balance

Số dư bằng đô la, và có đủ để mua qua API hay không.

curl -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/balance

Phản hồi

{ "balance": 25, "currency": "USD", "canBuy": true, "apiMinimum": 20 }

GET /services

Mọi dịch vụ đang bán: id của chúng tôi, tên và mã handler_api.php.

Tham sốBắt buộcMô tả
lang querykhôngNgôn ngữ của tên: en (mặc định), ru, uk, zh, es, pt, id, vi, tr, ar, fr.
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/services?lang=en"

Phản hồi

{ "services": [{ "id": "telegram", "name": "Telegram", "protocolCode": "tg" }] }

GET /countries

Mọi quốc gia đang bán: mã ISO, tên và mã handler_api.php.

Tham sốBắt buộcMô tả
lang querykhôngNgôn ngữ của tên: en (mặc định), ru, uk, zh, es, pt, id, vi, tr, ar, fr.
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/countries?lang=en"

Phản hồi

{ "countries": [{ "id": "US", "name": "United States", "protocolCode": 187 }] }

GET /prices

Giá của chúng tôi bằng đô la và số lượng số ước tính. Không tham số — mọi thứ đang bán.

Tham sốBắt buộcMô tả
service querykhôngId dịch vụ từ /services, ví dụ telegram.
country querykhôngMã ISO quốc gia từ /countries, ví dụ US.
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/prices?service=telegram"

Phản hồi

{ "prices": [{ "service": "telegram", "country": "US", "price": 0.59, "stock": 1000 }] }

Lỗi có thể gặp: unknown_service, unknown_country

POST /orders

Mua số. Trừ tiền ngay; hoàn lại nếu không có mã.

Tham sốBắt buộcMô tả
service bodycóId dịch vụ từ /services, ví dụ telegram.
country bodycóMã ISO quốc gia từ /countries, ví dụ US.
maxPrice bodykhôngGiá tối đa bằng đô la, dạng số. Cao hơn — price_above_max kèm giá hiện tại, không trừ tiền.
curl -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7c1f0e2a-run-1" \
  -d '{"service":"telegram","country":"US","maxPrice":0.8}' \
  https://relysms.pro/api/v1/orders

Phản hồi

{
  "order": {
    "id": 1042,
    "service": "telegram",
    "country": "US",
    "phone": "15550001111",
    "price": 0.59,
    "status": "waiting",
    "refunded": false,
    "codes": [],
    "awaitingAnotherCode": false,
    "createdAt": "2026-10-27T10:00:00.000Z",
    "expiresAt": "2026-10-27T10:20:00.000Z",
    "cancelableAt": "2026-10-27T10:02:00.000Z"
  }
}

Lỗi có thể gặp: bad_request, unknown_service, unknown_country, no_numbers, insufficient_balance, below_api_minimum, price_above_max, too_many_open_orders, buying_too_fast, idempotency_key_reused, idempotency_in_progress

POST /orders/batch

Mua tối đa 20 số cho một dịch vụ và quốc gia trong một yêu cầu.

Tham sốBắt buộcMô tả
service bodycóId dịch vụ từ /services, ví dụ telegram.
country bodycóMã ISO quốc gia từ /countries, ví dụ US.
quantity bodycóSố lượng số, từ 1 đến 20.
maxPrice bodykhôngGiá tối đa bằng đô la, dạng số. Cao hơn — price_above_max kèm giá hiện tại, không trừ tiền.
curl -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7c1f0e2a-batch-1" \
  -d '{"service":"telegram","country":"US","quantity":5}' \
  https://relysms.pro/api/v1/orders/batch

Phản hồi

{
  "orders": [{ "id": 1043, "phone": "15550001112", … }, { "id": 1044, … }],
  "requested": 5,
  "placed": 2,
  "stoppedBy": { "code": "no_numbers", "message": "…" }
}

Lỗi có thể gặp: bad_request, unknown_service, unknown_country, no_numbers, insufficient_balance, below_api_minimum, price_above_max, too_many_open_orders, buying_too_fast, idempotency_key_reused, idempotency_in_progress

GET /orders

Các đơn của bạn, mới nhất trước: mặc định là đơn đang mở, hoặc tất cả.

Tham sốBắt buộcMô tả
status querykhôngopen (mặc định) — đang chờ hoặc đã có mã; all — mọi đơn.
limit querykhôngSố đơn mỗi trang, từ 1 đến 100 (mặc định 50).
before querykhôngGiá trị next của trang trước.
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/orders?status=all&limit=50"

Phản hồi

{ "orders": [{ "id": 1042, … }], "next": "1001" }

Lỗi có thể gặp: bad_request

GET /orders/{id}

Một đơn kèm mã. Hỏi mỗi 5–10 giây khi trạng thái là waiting.

Tham sốBắt buộcMô tả
id pathcóId đơn trong phản hồi mua.
curl -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042

Phản hồi

{
  "order": {
    "id": 1042,
    "status": "received",
    "codes": [{ "code": "48213", "text": "Telegram code: 48213", "receivedAt": "2026-10-27T10:01:12.000Z" }],
    …
  }
}

Lỗi có thể gặp: not_found

POST /orders/{id}/finish

Hoàn tất đơn đã có mã. Số sẽ không nhận thêm SMS. Gọi lại không sao.

Tham sốBắt buộcMô tả
id pathcóId đơn trong phản hồi mua.
curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042/finish

Phản hồi

{ "order": { "id": 1042, "status": "finished", … } }

Lỗi có thể gặp: not_found, invalid_state

POST /orders/{id}/another-code

Thêm một mã cho cùng số — sau mã đầu tiên, khi đơn còn mở. Miễn phí. Cho đến khi mã mới đến, đơn có awaitingAnotherCode = true.

Tham sốBắt buộcMô tả
id pathcóId đơn trong phản hồi mua.
curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042/another-code

Phản hồi

{ "order": { "id": 1042, "status": "received", "awaitingAnotherCode": true, … } }

Lỗi có thể gặp: not_found, invalid_state, try_later

POST /orders/{id}/cancel

Hủy đơn chưa có mã, từ 2 phút sau khi mua. Tiền về ngay.

Tham sốBắt buộcMô tả
id pathcóId đơn trong phản hồi mua.
curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042/cancel

Phản hồi

{ "order": { "id": 1042, "status": "cancelled", "refunded": true, … } }

Lỗi có thể gặp: not_found, invalid_state, too_early_to_cancel

GET /webhook

Địa chỉ webhook và secret ký, hoặc null.

curl -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/webhook

Phản hồi

{ "webhook": { "url": "https://example.com/relysms-hook", "secret": "whsec_…", "createdAt": "2026-10-27T10:00:00.000Z" } }

PUT /webhook

Đặt hoặc đổi địa chỉ. Secret được tạo một lần và giữ nguyên; rotateSecret tạo secret mới.

Tham sốBắt buộcMô tả
url bodycóĐịa chỉ HTTPS của máy chủ bạn. Địa chỉ riêng và cục bộ bị từ chối.
rotateSecret bodykhôngtrue — tạo secret ký mới.
curl -X PUT -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/relysms-hook"}' \
  https://relysms.pro/api/v1/webhook

Phản hồi

{ "webhook": { "url": "https://example.com/relysms-hook", "secret": "whsec_…", "createdAt": "2026-10-27T10:00:00.000Z" } }

Lỗi có thể gặp: bad_request, invalid_webhook_url

DELETE /webhook

Xóa webhook. Sự kiện chưa gửi sẽ bị bỏ.

curl -X DELETE -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/webhook

Phản hồi

{ "webhook": null }

POST /webhook/test

Gửi sự kiện ping để kiểm tra địa chỉ và chữ ký.

curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/webhook/test

Phản hồi

{ "delivery": { "id": "cm…" } }

Lỗi có thể gặp: not_found

GET /webhook/deliveries

20 lần gửi gần nhất: sự kiện, trạng thái, số lần thử, phản hồi cuối của máy chủ bạn.

curl -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/webhook/deliveries

Phản hồi

{
  "deliveries": [{
    "id": "cm…", "event": "order.code_received", "orderId": 1042,
    "status": "pending", "attempts": 2, "lastHttpStatus": 502, "lastError": "HTTP 502",
    "createdAt": "2026-10-27T10:01:12.000Z", "deliveredAt": null, "nextAttemptAt": "2026-10-27T10:02:22.000Z"
  }]
}

Trạng thái đơn

Trường status của đơn:

  • waiting — Số là của bạn, chưa có mã.
  • received — Đã có mã, nằm trong codes. Có thể có thêm mã khi đơn còn mở.
  • finished — Bạn đã hoàn tất đơn (hoặc hết thời gian sau khi có mã).
  • cancelled — Đã hủy khi chưa có mã; refunded là true và tiền đã ở số dư.
  • expired — Hết thời gian mà không có mã; tiền đã về số dư.

Lỗi

Lỗi gồm mã trạng thái HTTP và JSON có code để chương trình xử lý và message cho người đọc. Một số có thêm trường (price, cancelableAt, apiMinimum).

{ "error": { "code": "price_above_max", "message": "The price is above maxPrice.", "price": 0.59 } }
missing_key401Không có khóa trong Authorization hoặc X-Api-Key.
invalid_key401Khóa sai, đã bị thay, hoặc tài khoản bị khóa.
bad_request400Nội dung hoặc tham số sai; message cho biết chỗ nào.
unknown_service400Không có id dịch vụ này.
unknown_country400Không có mã quốc gia này.
idempotency_key_invalid400Idempotency-Key trống hoặc dài hơn 255 ký tự.
invalid_webhook_url400Địa chỉ webhook không phải HTTPS, không phải URL, hoặc trỏ tới máy chủ riêng hay cục bộ.
insufficient_balance402Số dư thấp hơn giá.
below_api_minimum402Số dư dưới $20 — API chỉ mua khi từ $20.
account_blocked403Tài khoản bị khóa — hãy liên hệ hỗ trợ.
not_found404Không có đơn với id này cho khóa này.
no_numbers409Hiện không có số cho cặp này; không trừ tiền.
price_above_max409Giá vượt maxPrice; price chứa giá hiện tại.
too_many_open_orders409Quá nhiều đơn đang mở — hãy hoàn tất hoặc hủy bớt.
invalid_state409Không thể ở trạng thái này (ví dụ hoàn tất khi chưa có mã).
too_early_to_cancel409Có thể hủy từ cancelableAt, 2 phút sau khi mua.
idempotency_in_progress409Yêu cầu với Idempotency-Key này vẫn đang chạy; thử lại sau giây lát.
idempotency_key_reused422Idempotency-Key này đã dùng cho một yêu cầu khác.
rate_limited429Hơn 20 yêu cầu mỗi giây; Retry-After cho biết khi nào thử lại.
buying_too_fast429Hơn 5 lượt mua mỗi giây; hãy dùng /orders/batch.
try_later503Tạm thời không thành công — thử lại sau một phút.

Ví dụ REST

Mua số, chờ mã, hoàn tất đơn.

Python

import time, uuid, requests

BASE = "https://relysms.pro/api/v1"
S = requests.Session()
S.headers["Authorization"] = "Bearer rs_your_key"

r = S.post(f"{BASE}/orders",
           json={"service": "telegram", "country": "US", "maxPrice": 0.8},
           headers={"Idempotency-Key": str(uuid.uuid4())}, timeout=30)
if r.status_code != 201:
    raise SystemExit(r.json()["error"])   # no_numbers, below_api_minimum, …
order = r.json()["order"]
print("number:", order["phone"])

while order["status"] == "waiting":       # up to 20 minutes
    time.sleep(10)
    order = S.get(f"{BASE}/orders/{order['id']}", timeout=30).json()["order"]

if order["status"] == "received":
    print("code:", order["codes"][-1]["code"])
    S.post(f"{BASE}/orders/{order['id']}/finish", timeout=30)
# "expired" or "cancelled": the money is back on the balance

Node.js

const BASE = "https://relysms.pro/api/v1";
const headers = { Authorization: "Bearer rs_your_key", "Content-Type": "application/json" };

const res = await fetch(`${BASE}/orders`, {
  method: "POST",
  headers: { ...headers, "Idempotency-Key": crypto.randomUUID() },
  body: JSON.stringify({ service: "telegram", country: "US", maxPrice: 0.8 }),
});
if (res.status !== 201) throw new Error((await res.json()).error.code);
let { order } = await res.json();
console.log("number:", order.phone);

while (order.status === "waiting") {
  await new Promise((r) => setTimeout(r, 10_000));
  ({ order } = await (await fetch(`${BASE}/orders/${order.id}`, { headers })).json());
}
if (order.status === "received") {
  console.log("code:", order.codes.at(-1).code);
  await fetch(`${BASE}/orders/${order.id}/finish`, { method: "POST", headers });
}

Ví dụ

Chu trình đầy đủ: mua số, chờ mã, hoàn tất đơn.

curl

KEY=rs_your_key
BASE=https://relysms.pro/stubs/handler_api.php

curl "$BASE?api_key=$KEY&action=getBalance"
curl "$BASE?api_key=$KEY&action=getNumber&service=tg&country=187&maxPrice=0.80"
# → ACCESS_NUMBER:1042:15550001111
curl "$BASE?api_key=$KEY&action=getStatus&id=1042"
# → STATUS_WAIT_CODE … then STATUS_OK:48213
curl "$BASE?api_key=$KEY&action=setStatus&id=1042&status=6"

Python

import time, requests

BASE = "https://relysms.pro/stubs/handler_api.php"
KEY = "rs_your_key"

def call(action, **params):
    r = requests.get(BASE, params={"api_key": KEY, "action": action, **params}, timeout=30)
    r.raise_for_status()
    return r.text

answer = call("getNumber", service="tg", country="187", maxPrice="0.80")
if not answer.startswith("ACCESS_NUMBER"):
    raise SystemExit(answer)          # NO_NUMBERS, NO_BALANCE, …
_, order_id, phone = answer.split(":")
print("number:", phone)

for _ in range(120):                  # up to 20 minutes, every 10 s
    status = call("getStatus", id=order_id)
    if status.startswith("STATUS_OK:"):
        print("code:", status.split(":", 1)[1])
        call("setStatus", id=order_id, status=6)
        break
    if status == "STATUS_CANCEL":
        break                         # refunded automatically
    time.sleep(10)

Node.js

const BASE = "https://relysms.pro/stubs/handler_api.php";
const KEY = "rs_your_key";

async function call(action, params = {}) {
  const url = new URL(BASE);
  url.search = new URLSearchParams({ api_key: KEY, action, ...params });
  const res = await fetch(url);
  return res.text();
}

const answer = await call("getNumber", { service: "tg", country: "187", maxPrice: "0.80" });
if (!answer.startsWith("ACCESS_NUMBER")) throw new Error(answer);
const [, id, phone] = answer.split(":");
console.log("number:", phone);

for (let i = 0; i < 120; i++) {
  const status = await call("getStatus", { id });
  if (status.startsWith("STATUS_OK:")) {
    console.log("code:", status.slice("STATUS_OK:".length));
    await call("setStatus", { id, status: "6" });
    break;
  }
  if (status === "STATUS_CANCEL") break; // refunded automatically
  await new Promise((r) => setTimeout(r, 10_000));
}

Câu hỏi

Phần mềm của tôi từng dùng dịch vụ kích hoạt khác. Cần đổi gì?

Đổi địa chỉ máy chủ thành https://relysms.pro/stubs/handler_api.php và khóa thành khóa trong tài khoản của bạn. Mã dịch vụ và quốc gia giữ nguyên.

Vì sao NO_BALANCE dù vẫn còn tiền?

Mua qua API cần số dư từ $20 trở lên. Tài khoản web và Mini App không có ngưỡng này.

Tiền sẽ ra sao nếu không có mã?

Tự về số dư khi hết thời gian, hoặc về ngay nếu bạn hủy sau 2 phút.

Có nhận được mã thứ hai trên cùng số không?

Có, khi còn thời gian: gọi setStatus=3 rồi getStatus tiếp.

Có chế độ thử không?

Không: mọi lượt mua đều thật. Hãy bắt đầu với cặp rẻ và thử quy trình trên một số.

Khóa bị lộ thì làm sao?

Tài khoản → Số dư → API → Cấp khóa mới. Khóa cũ ngừng hoạt động ngay.

Cho trợ lý AI

Toàn bộ tài liệu dạng một văn bản cho ChatGPT, Claude và các mô hình khác ở /vi/developers.md, bản đồ ngắn ở /llms.txt. Đưa liên kết cho mô hình và nhờ kết nối RelySMS vào mã của bạn.

Đọc https://relysms.pro/vi/developers.md và kết nối RelySMS vào script của tôi.

developers.md · llms.txt