getBalance
The account balance in dollars.
Only api_key and action.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getBalanceAnswer
ACCESS_BALANCE:25.00If your software already works with an activation service over handler_api.php, it works with RelySMS: change the server address and the key. Same actions, same answers, our prices and refunds.
https://relysms.pro/stubs/handler_api.phpEvery request is a GET or POST to one address, with parameters in the query string or a form body. The key goes in api_key, the action in action.
getBalanceThe account balance in dollars.
Only api_key and action.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getBalanceAnswer
ACCESS_BALANCE:25.00getNumberBuy a number for a service in a country. Charged at once; refunded if no code comes. Answer: ACCESS_NUMBER:order_number:phone.
| Parameter | Required | Description |
|---|---|---|
service | yes | Service code (getServicesList), e.g. tg. |
country | yes | Country code (getCountries). |
maxPrice | no | Maximum price in dollars. Above it — WRONG_MAX_PRICE with the current price, nothing charged. |
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getNumber&service=tg&country=187&maxPrice=0.80Answer
ACCESS_NUMBER:1042:15550001111Possible errors: BAD_SERVICE, BAD_COUNTRY, NO_NUMBERS, NO_BALANCE, WRONG_MAX_PRICE:0.59, LIMIT_ACTIVATIONS, RATE_LIMIT, BANNED
getNumberV2The same as getNumber, answered as JSON with the price and the window's times.
| Parameter | Required | Description |
|---|---|---|
service | yes | Service code. |
country | yes | Country code. |
maxPrice | no | Maximum price in dollars. |
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getNumberV2&service=tg&country=187&maxPrice=0.80Answer
{
"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"
}Possible errors: BAD_SERVICE, BAD_COUNTRY, NO_NUMBERS, NO_BALANCE, WRONG_MAX_PRICE:0.59, LIMIT_ACTIVATIONS, RATE_LIMIT
getStatusThe order's status: waiting, code received (with the code), or cancelled.
| Parameter | Required | Description |
|---|---|---|
id | yes | Order number from getNumber. |
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getStatus&id=1042Answer
STATUS_OK:48213Possible errors: NO_ACTIVATION
setStatusAct on an order: ready, another code, finish, cancel (see Statuses).
| Parameter | Required | Description |
|---|---|---|
id | yes | Order number. |
status | yes | 1, 3, 6 or 8. |
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=setStatus&id=1042&status=6Answer
ACCESS_ACTIVATIONPossible errors: NO_ACTIVATION, BAD_STATUS, EARLY_CANCEL_DENIED, ERROR_SQL
getActiveActivationsEvery open order of the key: number, status, codes and texts received.
Only api_key and action.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getActiveActivationsAnswer
{
"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"
}
]
}getPricesOur prices in dollars and roughly how many numbers. Without parameters — everything on sale.
| Parameter | Required | Description |
|---|---|---|
service | no | Only this service. |
country | no | Only this country. |
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getPrices&service=tg&country=187Answer
{ "187": { "tg": { "cost": 0.59, "count": 1000 } } }Possible errors: BAD_SERVICE, BAD_COUNTRY
getCountriesCountries with protocol codes and names in Russian and English.
Only api_key and action.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getCountriesAnswer
{ "187": { "id": 187, "rus": "США", "eng": "United States", "visible": 1 } }getServicesListServices with protocol codes.
Only api_key and action.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getServicesListAnswer
{ "status": "success", "services": [{ "code": "tg", "name": "Telegram" }] }Values of status in setStatus:
status=1 → ACCESS_READY — The number is entered in the service, waiting for the code. Changes nothing; kept for compatibility.status=3 → ACCESS_RETRY_GET — Ask for another code on the same number — after the first code, while the order is open. Free. Until it comes, getStatus answers STATUS_WAIT_RETRY.status=6 → ACCESS_ACTIVATION — Finish the order after the code. No more SMS will reach the number.status=8 → ACCESS_CANCEL — Cancel an order without a code (not before 2 minutes). The money returns to your balance.getStatus answers:
STATUS_WAIT_CODE — No code yet — ask again in 5–10 seconds.STATUS_OK:48213 — The code arrived; after the colon is the code (or the SMS text if it has no code).STATUS_WAIT_RETRY:48213 — Another code was asked for and hasn't come yet; after the colon is the previous code.STATUS_CANCEL — Cancelled or closed without a code; the money is already back.Errors are plain strings, as is usual for this protocol. All but RATE_LIMIT come with status 200.
NO_KEY | api_key is missing. |
BAD_KEY | Wrong or disabled key, or a blocked account. |
BAD_ACTION | Unknown action. |
BAD_SERVICE | No such service code. |
BAD_COUNTRY | No such country code. |
NO_NUMBERS | No numbers for this pair right now; nothing charged. |
NO_BALANCE | Less than $20 on the balance (the API floor), or less than the price. |
WRONG_MAX_PRICE | The price is above maxPrice; the current price follows the colon. |
LIMIT_ACTIVATIONS | Too many open orders — finish or cancel some. |
RATE_LIMIT | Too frequent; HTTP 429. Retry in a second. |
BANNED | The account is blocked — contact support. |
NO_ACTIVATION | No order with that number for this key. |
BAD_STATUS | That action isn't available for the order now (e.g. finishing without a code). |
EARLY_CANCEL_DENIED | Cancelling is allowed 2 minutes after the purchase. |
ERROR_SQL | A temporary error on our side — repeat the request in a minute. |
The codes are the protocol's standard ones: tg — Telegram, wa — WhatsApp and so on; country 187 — the US. getServicesList and getCountries return the full lists — take codes from there, not from old tables: services and countries change with stock.
The same numbers and the same rules as handler_api.php, as JSON: services by name (telegram), countries by ISO code (US), HTTP statuses and error codes a program can branch on. Use it for new code; keep handler_api.php for software that already speaks it.
https://relysms.pro/api/v1Send the key in a header: Authorization: Bearer <key> (or X-Api-Key: <key>). Never in the URL — URLs end up in logs. The limits, the $20 floor and the catalogue are the same as for handler_api.php.
Send Idempotency-Key with a value of your own (a UUID, up to 255 characters) on POST /orders and /orders/batch. If the connection drops and you repeat the request with the same key, you get the first answer back (with the header Idempotent-Replayed: true) and nothing is bought twice. The same key with a different body is refused; a repeat that arrives while the first is still running gets idempotency_in_progress. Successful answers are kept for 24 hours; a purchase that failed charged nothing and can be repeated with the same key.
POST /orders/batch buys up to 20 numbers for one service and country in one request — this is the way to buy faster than 5 a second. Purchases go one by one; the first that fails stops the batch, and the answer lists what was bought plus the reason in stoppedBy. If nothing was bought, the answer is that error.
GET /orders returns the newest first. When next is not null, pass it as before to get the next page.
Instead of polling GET /orders/{id}, set an HTTPS address with PUT /webhook and we POST to it when something happens to an order bought through the API. The body carries the order as it is at the moment of sending. Answer with any 2xx within 10 seconds; one order can produce several events, and the same event can come twice after a retry, so key on the delivery id.
order.code_received — A code arrived (each new one sends this again).order.finished — The order was finished — by you, or when its time ran out after a code.order.cancelled — Cancelled with no code; the money is back on the balance.order.expired — Time ran out with no code; the money is back on the balance.ping — A test from POST /webhook/test; order is 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", … }], … }
}Every request carries X-RelySMS-Signature: t=<unix time>,v1=<signature>. The signature is HMAC-SHA256 of the string "t.body" (the raw body, byte for byte) with your webhook secret, in hex. Check it, and that t is within 5 minutes, before trusting the body.
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));
}If your server doesn't answer 2xx, we retry after 10 seconds, 1 minute, 5 minutes, 30 minutes, 2 hours and 6 hours — 7 attempts in all — then give up. GET /webhook/deliveries shows what was sent and what failed.
GET /balanceThe balance in dollars, and whether it is enough to buy through the API.
curl -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/balanceAnswer
{ "balance": 25, "currency": "USD", "canBuy": true, "apiMinimum": 20 }GET /servicesEvery service on offer: our id, the name and the handler_api.php code.
| Parameter | Required | Description |
|---|---|---|
lang query | no | Language of the names: en (default), ru, uk, zh, es, pt, id, vi, tr, ar, fr. |
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/services?lang=en"Answer
{ "services": [{ "id": "telegram", "name": "Telegram", "protocolCode": "tg" }] }GET /countriesEvery country on offer: ISO code, name and the handler_api.php code.
| Parameter | Required | Description |
|---|---|---|
lang query | no | Language of the names: en (default), ru, uk, zh, es, pt, id, vi, tr, ar, fr. |
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/countries?lang=en"Answer
{ "countries": [{ "id": "US", "name": "United States", "protocolCode": 187 }] }GET /pricesOur prices in dollars and roughly how many numbers are available. Without parameters, everything on sale.
| Parameter | Required | Description |
|---|---|---|
service query | no | Service id from /services, e.g. telegram. |
country query | no | Country ISO code from /countries, e.g. US. |
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/prices?service=telegram"Answer
{ "prices": [{ "service": "telegram", "country": "US", "price": 0.59, "stock": 1000 }] }Possible errors: unknown_service, unknown_country
POST /ordersBuy a number. The money is charged at once and returned if no code arrives.
| Parameter | Required | Description |
|---|---|---|
service body | yes | Service id from /services, e.g. telegram. |
country body | yes | Country ISO code from /countries, e.g. US. |
maxPrice body | no | Highest price in dollars, a number. Above it — price_above_max with the current price, nothing charged. |
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/ordersAnswer
{
"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"
}
}Possible errors: 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/batchBuy up to 20 numbers for one service and country in one request.
| Parameter | Required | Description |
|---|---|---|
service body | yes | Service id from /services, e.g. telegram. |
country body | yes | Country ISO code from /countries, e.g. US. |
quantity body | yes | How many numbers, 1 to 20. |
maxPrice body | no | Highest price in dollars, a number. Above it — price_above_max with the current price, nothing charged. |
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/batchAnswer
{
"orders": [{ "id": 1043, "phone": "15550001112", … }, { "id": 1044, … }],
"requested": 5,
"placed": 2,
"stoppedBy": { "code": "no_numbers", "message": "…" }
}Possible errors: 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 /ordersYour orders, newest first: the open ones by default, or all.
| Parameter | Required | Description |
|---|---|---|
status query | no | open (default) — waiting or with a code; all — every order. |
limit query | no | Orders per page, 1 to 100 (default 50). |
before query | no | The next value from the previous page. |
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/orders?status=all&limit=50"Answer
{ "orders": [{ "id": 1042, … }], "next": "1001" }Possible errors: bad_request
GET /orders/{id}One order with its codes. Poll it every 5–10 seconds while the status is waiting.
| Parameter | Required | Description |
|---|---|---|
id path | yes | The order id from the purchase answer. |
curl -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042Answer
{
"order": {
"id": 1042,
"status": "received",
"codes": [{ "code": "48213", "text": "Telegram code: 48213", "receivedAt": "2026-10-27T10:01:12.000Z" }],
…
}
}Possible errors: not_found
POST /orders/{id}/finishFinish an order that has a code. The number will take no more SMS. Repeating is harmless.
| Parameter | Required | Description |
|---|---|---|
id path | yes | The order id from the purchase answer. |
curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042/finishAnswer
{ "order": { "id": 1042, "status": "finished", … } }Possible errors: not_found, invalid_state
POST /orders/{id}/another-codeAnother code on the same number — after the first code, while the order is open. Free. Until it comes, the order has awaitingAnotherCode = true.
| Parameter | Required | Description |
|---|---|---|
id path | yes | The order id from the purchase answer. |
curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042/another-codeAnswer
{ "order": { "id": 1042, "status": "received", "awaitingAnotherCode": true, … } }Possible errors: not_found, invalid_state, try_later
POST /orders/{id}/cancelCancel an order with no code, from 2 minutes after purchase. The money goes back at once.
| Parameter | Required | Description |
|---|---|---|
id path | yes | The order id from the purchase answer. |
curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042/cancelAnswer
{ "order": { "id": 1042, "status": "cancelled", "refunded": true, … } }Possible errors: not_found, invalid_state, too_early_to_cancel
GET /webhookThe webhook address and its signing secret, or null.
curl -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/webhookAnswer
{ "webhook": { "url": "https://example.com/relysms-hook", "secret": "whsec_…", "createdAt": "2026-10-27T10:00:00.000Z" } }PUT /webhookSet or change the address. The secret is made once and kept; rotateSecret makes a new one.
| Parameter | Required | Description |
|---|---|---|
url body | yes | HTTPS address of your server. Private and local addresses are refused. |
rotateSecret body | no | true — make a new signing secret. |
curl -X PUT -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"url":"https://example.com/relysms-hook"}' \
https://relysms.pro/api/v1/webhookAnswer
{ "webhook": { "url": "https://example.com/relysms-hook", "secret": "whsec_…", "createdAt": "2026-10-27T10:00:00.000Z" } }Possible errors: bad_request, invalid_webhook_url
DELETE /webhookRemove the webhook. Events not yet sent are dropped.
curl -X DELETE -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/webhookAnswer
{ "webhook": null }POST /webhook/testSend a ping event to check the address and the signature.
curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/webhook/testAnswer
{ "delivery": { "id": "cm…" } }Possible errors: not_found
GET /webhook/deliveriesThe last 20 deliveries: event, status, attempts, your server's last answer.
curl -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/webhook/deliveriesAnswer
{
"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"
}]
}The status field of an order:
waiting — The number is yours and no code has come yet.received — A code has come; it is in codes. More codes can come while the order is open.finished — You finished the order (or its time ran out after a code).cancelled — Cancelled with no code; refunded is true and the money is on the balance.expired — Time ran out with no code; the money is back on the balance.An error is an HTTP status and a JSON body with a code to branch on and a message for people. Some carry extra fields (price, cancelableAt, apiMinimum).
{ "error": { "code": "price_above_max", "message": "The price is above maxPrice.", "price": 0.59 } }missing_key | 401 | No key in Authorization or X-Api-Key. |
invalid_key | 401 | The key is wrong, was replaced, or the account is blocked. |
bad_request | 400 | The body or a parameter is wrong; message says which. |
unknown_service | 400 | No such service id. |
unknown_country | 400 | No such country code. |
idempotency_key_invalid | 400 | Idempotency-Key is empty or longer than 255 characters. |
invalid_webhook_url | 400 | The webhook address is not HTTPS, not a URL, or points to a private or local server. |
insufficient_balance | 402 | The balance is below the price. |
below_api_minimum | 402 | Less than $20 on the balance — the API buys only from $20. |
account_blocked | 403 | The account is blocked — write to support. |
not_found | 404 | No order with this id for this key. |
no_numbers | 409 | No numbers for this pair right now; nothing charged. |
price_above_max | 409 | The price is above maxPrice; price holds the current one. |
too_many_open_orders | 409 | Too many open orders — finish or cancel some. |
invalid_state | 409 | Not possible in this status (e.g. finishing without a code). |
too_early_to_cancel | 409 | Cancelling is possible from cancelableAt, 2 minutes after purchase. |
idempotency_in_progress | 409 | A request with this Idempotency-Key is still running; repeat in a moment. |
idempotency_key_reused | 422 | This Idempotency-Key was already used for a different request. |
rate_limited | 429 | More than 20 requests a second; Retry-After says when to repeat. |
buying_too_fast | 429 | More than 5 purchases a second; use /orders/batch. |
try_later | 503 | Temporarily didn't work — try again in a minute. |
Buy a number, wait for the code, finish the order.
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 balanceNode.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 });
}The whole cycle: buy a number, wait for the code, finish the order.
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));
}The server address — to https://relysms.pro/stubs/handler_api.php; the key — to the one from your account. Service and country codes stay the same.
API purchases need a balance of $20 or more. The account and Mini App have no such floor.
It returns to your balance on its own when the window closes, or at once if you cancel after 2 minutes.
Yes, while the window is open: setStatus=3, then getStatus again.
No: every purchase is real. Start with a cheap pair and check your flow on one number.
Account → Balance → API → Issue a new one. The old key stops working at once.
The full docs as one text for ChatGPT, Claude and other models are at /developers.md, a short map at /llms.txt. Give the model the link and ask it to connect RelySMS to your code.
Read https://relysms.pro/developers.md and connect RelySMS to my script.