API documentation
Numbers, messages and earnings, directly from your app.
Start with one request
Create an API key in your dashboard, get a number and check for messages every 20 seconds. Payment is credited when an SMS with a code arrives; reading it again does not affect your balance.
https://smscash.org/api/v1https://smscash.org/stubs/handler_api.phpcurl -X POST 'https://smscash.org/api/v1/activations' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: request-unique-001' \
-d '{"service":"go","country":86}'Alternative compatible interface address: /handler_api.php. Existing REST integrations continue to work.
Request builder
Idempotency-Key: UUID · POST · 8–128
Auto-select: most codes in the past hour, then 24 hours. No numbers: next operator.
curl --max-time 15 --fail-with-body -X POST 'https://smscash.org/api/v1/activations' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: request-unique-001' \
--data '{"service":"go","country":86}'package main
import (
"bytes"
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
payload := []byte("{\"service\":\"go\",\"country\":86}")
req, err := http.NewRequest("POST", "https://smscash.org/api/v1/activations", bytes.NewReader(payload))
if err != nil { panic(err) }
req.Header.Set("Authorization", "Bearer " + os.Getenv("SMSCASH_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", "request-unique-001")
client := &http.Client{Timeout: 15 * time.Second, CheckRedirect: func(_ *http.Request, _ []*http.Request) error { return http.ErrUseLastResponse }}
res, err := client.Do(req)
if err != nil { panic(err) } // Keep the same operation key after a network error.
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil { panic(err) }
if res.StatusCode >= 300 {
fmt.Fprintf(os.Stderr, "HTTP %d, request_id=%s\n%s\n", res.StatusCode, res.Header.Get("X-Request-ID"), body)
os.Exit(1)
}
fmt.Println(string(body))
}// Node.js 18+: set SMSCASH_API_KEY in your environment.
const response = await fetch("https://smscash.org/api/v1/activations", {
method: "POST",
headers: {
Authorization: 'Bearer ' + process.env.SMSCASH_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': "request-unique-001",
},
body: JSON.stringify({
"service": "go",
"country": 86
}),
signal: AbortSignal.timeout(15000),
redirect: 'error',
});
const result = await response.json();
if (!response.ok) {
const error = result.error || {};
console.error(response.status, error.code, error.hint, error.request_id);
throw new Error(error.message || 'API error');
}
console.log(result);
// SMS codes are strings: keep leading zeros. Never retry writes automatically.import json
import os
import urllib.error
import urllib.request
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
'Authorization': 'Bearer ' + os.environ['SMSCASH_API_KEY'],
'Content-Type': 'application/json',
'Idempotency-Key': "request-unique-001",
}
request = urllib.request.Request(
"https://smscash.org/api/v1/activations",
headers=headers,
data="{\"service\":\"go\",\"country\":86}".encode('utf-8'),
method="POST",
)
try:
with urllib.request.build_opener(NoRedirect).open(request, timeout=15) as response:
result = json.load(response)
print(result)
except urllib.error.HTTPError as error:
details = json.load(error).get('error', {})
print(error.code, details.get('code'), details.get('hint'), details.get('request_id'))
raise
# No automatic retries; SMS codes remain strings.The key is not stored. This check does not issue numbers.
REST for new integrations
Services and countries
Choose a service and country. Payment per SMS depends on the country.
GET /api/v1/catalog?service=go&country=86&page=1&page_size=100
Authorization: Bearer YOUR_API_KEY{
"rows": [
{
"offer_id": 42,
"service": "go",
"service_name": "Google",
"country_id": 86,
"country_name": "Italy",
"provider_id": 1,
"operator": 1,
"provider_name": "Operator 1",
"reward": "0.00300000",
"currency": "USD",
"accounting_precision": 8,
"earnings_hold_days": 45
}
],
"page": 1,
"page_size": 100,
"total": 1,
"pages": 1,
"has_more": false,
"accounting_precision": 8
}service · country · operator · q · page · page_size (1–100)
Get a number
POST /api/v1/activations
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Idempotency-Key: request-unique-001
{
"service": "go",
"country": 86
}Auto-select: most codes in the past hour, then 24 hours. No numbers: next operator.
201: new session · 200: replay of the same operation
service + country OR offer_id · duration_minutes: 20
ref: software owner code (optional)
operator: public ID (e.g. 1 for Operator 1), optional · any/0: automatic
country: integer · service: string · SMS code: stringThe number is valid for 20 minutes. SMS is checked every 20 seconds. You can cancel immediately.
Check multiple numbers
GET /api/v1/activations/batch?ids=42,43
Authorization: Bearer YOUR_API_KEY{
"rows": [
{
"id": 42,
"found": true,
"phone": "12025550123",
"status": "received",
"service": "go",
"country_id": 86,
"provider_id": 1,
"operator": 1,
"expires_at": "2026-10-10T12:15:00Z",
"sms_count": 1,
"code": "001234",
"last_sms": {
"id": 101,
"code": "001234",
"sender": "Service",
"text": "Code: 001234",
"received_at": "2026-10-10T12:01:00Z"
}
},
{
"id": 43,
"found": false,
"error": {
"code": "NO_ACTIVATION",
"message": "Session not found."
}
}
],
"as_of": "2026-10-10T12:01:00Z",
"poll_interval_seconds": 20
}ids: 1–100 positive session IDs, separated by commas
Input order preserved · duplicates removed
Foreign, unavailable or out-of-scope IDs: found=false
Read only · no supplier requests · last_sms is the latest messageBalance · On hold
GET /api/v1/balance
Authorization: Bearer YOUR_API_KEY{
"currency": "USD",
"accounting_precision": 8,
"balance": "12.00000000",
"held_balance": "34.50000001",
"balance_minor": "1200000000",
"held_minor": "3450000001",
"as_of": "2026-10-12T20:00:00Z",
"next_release_at": "2026-11-26T20:00:00Z"
}balance — Available; held_balance — On hold. USD · 8
Only funds whose hold period has ended can be withdrawn.
Ready-to-use clients
import {SmScash, SmScashError} from './smscash.mjs';
import {randomUUID} from 'node:crypto';
const api = new SmScash(process.env.SMSCASH_API_KEY);
const catalog = await api.catalog({service: 'go', country: 86});
console.log(catalog.rows);
// Save this key before sending; keep it for retries of this operation.
const requestKey = randomUUID();
const session = await api.createNumber({service: 'go', country: 86}, requestKey);
// After 20 seconds:
const messages = await api.sms(session.id, {afterId: 0});
console.log(messages.sms);
const statuses = await api.batch([session.id]);
const held = await api.holdBalance();
console.log(held); // Exact USD stringimport os
import uuid
from smscash import SmScash, SmScashError
api = SmScash(os.environ['SMSCASH_API_KEY'])
catalog = api.catalog(service='go', country=86)
print(catalog['rows'])
# Save this key before sending; keep it for retries of this operation.
request_key = str(uuid.uuid4())
session = api.create_number({'service': 'go', 'country': 86}, request_key)
# After 20 seconds:
messages = api.sms(session['id'], after_id=0)
print(messages['sms'])
statuses = api.batch([session['id']])
held = api.hold_balance()
print(held) # Exact USD stringme() · balance() · holdBalance()/hold_balance() · catalog() · activation() · sms() · batch()
createNumber(parameters, requestKey) / create_number(parameters, request_key)
setStatus(id, "cancel") / set_status(id, "cancel")
setStatus(id, "retry", requestKey) / set_status(id, "retry", request_key)
Timeout: 15 s · no dependencies · no automatic retries
Error: code · status · hint · requestId/request_id · retryable
ALLOCATION_UNCERTAIN: contact support with request_id; never retry automatically.SMS-Activate / HeroSMS
https://smscash.org/sms-activate/stubs/handler_api.phphttps://smscash.org/hero-sms/stubs/handler_api.phpThe user’s personal API key.
Choose a service and country. Payment per SMS depends on the country.
| Code | Description |
|---|---|
getNumber / getNumberV2 | Get a number |
getStatus / getStatusV2 | Get the latest code |
setStatus / finishActivation / cancelActivation | Manage session |
getPrices / getNumbersStatus | Check availability |
getRewards (SMScash) | Reward for SMS |
getServicesList / getServices | Services |
getCountries / getOperators | Services and countries |
getActiveActivations | Sessions |
getBalance | User balance |
getHoldBalance (SMScash) | On hold |
cost = 0 USD · activationCost = 0 USDreward — Reward for SMS
curl --get 'https://smscash.org/hero-sms/stubs/handler_api.php' \
--data-urlencode 'api_key=YOUR_API_KEY' \
--data-urlencode 'action=getNumberV2' \
--data-urlencode 'service=go' \
--data-urlencode 'country=86' \
-H 'Idempotency-Key: request-unique-001'{
"activationId": "42",
"phoneNumber": "393331234567",
"activationCost": 0,
"currency": 840,
"countryCode": 86,
"canGetAnotherSms": true,
"activationTime": "2026-10-11T12:00:00Z",
"activationEndTime": "2026-10-11T12:15:00Z",
"reward": "0.00300000"
}GET or POST application/x-www-form-urlencoded
api_key · action · service · country · ref (optional)
setStatus: 1 → ACCESS_READY · 3 → ACCESS_RETRY_GET
6 → ACCESS_ACTIVATION · 8 → ACCESS_CANCEL
getStatus: STATUS_WAIT_CODE · STATUS_OK:001234 · STATUS_CANCEL
getStatusV2: {"verificationType":1,"sms":null,"call":null}
getServicesList: {"status":"success","services":[{"code":"go","name":"Google"}]}
getCountries: {"86":{"id":86,"eng":"Italy","visible":1,"retry":1,"rent":0}}
getPrices: {"86":{"go":{"cost":0,"count":12,"reward":"0.00300000","currency":"USD"}}}
getRewards: {"59":{"vi":{"1":"0.01000000"}}}
getRewards filters: country · service · operator (optional); any/0: all permitted providers
getActiveActivations: start=0 · limit=1–100 · activeActivations / data
Business/key errors: HTTP 200 + plain text · server errors: HTTP 500
Availability: actual supplier pool, shared cache up to 20 s; not a reservation
No automatic retries after a transport error or ALLOCATION_UNCERTAIN.
Keep the original Idempotency-Key and parameters.
Unsupported: rent · calls · forwarding · multiple services per number · prolong
Unsupported options return BAD_REQUEST; unsupported actions return BAD_ACTION.
SMScash keys and country/service codes; configure this base URL in your software.The number is valid for 20 minutes. SMS is checked every 20 seconds. You can cancel immediately.
Authentication and retries
REST: header Authorization: Bearer YOUR_API_KEY. Compatible Interface: parameters api_key and action. Use HTTPS.
To manage API keys, enter your account.
API request frequency and the number of phone numbers are unlimited. There are no daily or hourly quotas.
The number is valid for 20 minutes. SMS is checked every 20 seconds. You can cancel immediately.
In REST, a unique Idempotency-Key is required for number allocation, repeat allocation, retry and payout requests. It is optional but recommended in handler_api.php. Reuse the key when retrying a network request; use a new key for a new operation.
API key scope
You can restrict a key to specific services, countries and providers. Empty lists allow all available options.
{
"label": "My software",
"policy": {
"services": [
"go"
],
"countries": [
86
],
"providers": [
1
]
}
}PATCH /api/v1/keys/{id} changes the name and policy entirely. The secret is only shown when created.
10% in total. 5% + 5% with software code.
When issuing a number, please provide ref owner of the software. The request is authorized by the user's key. The code is in the "Referrals" section and in GET /api/v1/referrals → software_ref.
| Request | Inviter | Software |
|---|---|---|
| Without ref | 10% | — |
| With ref | 5% | 5% |
| With ref, no referrer | — | 5% |
The platform pays the bonus without reducing the user's earnings. The software owner and the referrer can be the same person. A user cannot use their own code.
Terms are fixed when a session is created; reading SMS and retry do not change them. Pass ref again for a new repeat session. In the tariff calculation, a user reward of USD 0.003 gives USD 0.00015 each to the software owner and referrer. The total bonus is USD 0.00030.
API commands
11 XVBC-style methods plus your SMScash balance.
GETgetNumberGet a number+
Creates a session and reserves an available number for the user. The reward rate and referral recipients are fixed at allocation; the reward is credited when an SMS with a code arrives.
Parameters
| Parameter | Type | Description |
|---|---|---|
api_key* | string | The user’s personal API key. |
service* | string | Available service codes. The answer is limited to the area of the API key. |
country* | integer | Take ID from getCountries. |
operator | string | Take ID from operators/getOperators (API). operator=1 · any/0 |
session_duration | integer | The session lasts 20 minutes. Pass 20 or omit this parameter. |
with_operator | integer | 1 adds the operator ID to the response; 0 or omission returns three segments. |
ref | string | Public code of the software owner: 5% for him and 5% for the inviter. Without ref - 10% to the inviter. |
* Required parameter. In all requests also pass action=getNumber.
Example request
curl 'https://smscash.org/stubs/handler_api.php?action=getNumber&api_key=YOUR_API_KEY&service=go&country=86&with_operator=1' \
-H 'Idempotency-Key: request-unique-001'package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://smscash.org/stubs/handler_api.php?action=getNumber&api_key=YOUR_API_KEY&service=go&country=86&with_operator=1", nil)
if err != nil { panic(err) }
req.Header.Set("Idempotency-Key", "request-unique-001")
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil { panic(err) }
fmt.Println(resp.StatusCode, string(body))
}const response = await fetch("https://smscash.org/stubs/handler_api.php?action=getNumber&api_key=YOUR_API_KEY&service=go&country=86&with_operator=1", {
headers: {"Idempotency-Key": "request-unique-001"}
});
const result = await response.text();
console.log(response.status, result);import requests
response = requests.get(
"https://smscash.org/stubs/handler_api.php?action=getNumber&api_key=YOUR_API_KEY&service=go&country=86&with_operator=1",
headers={"Idempotency-Key": "request-unique-001"},
timeout=15,
)
print(response.status_code, response.text)Responses
ACCESS_NUMBER:42:380670000000:1EMPTY_POOL- Auto-select: most codes in the past hour, then 24 hours. No numbers: next operator.
- Pass Idempotency-Key: the same request with the same key returns the previous session. Changing the parameters calls IDEMPOTENCY_CONFLICT.
- A numeric country without a pool gives EMPTY_POOL; the wrong country format is BAD_COUNTRY.
- The key of a deleted session remains used: replaying allocation with that key returns SESSION_CLOSED and does not issue another number.
- The allocation result is unconfirmed. Automatic retry is disabled to avoid allocating a second number.
GETgetNumbersStatusCheck availability+
Available phone numbers by service and country.
Parameters
| Parameter | Type | Description |
|---|---|---|
api_key* | string | The user’s personal API key. |
country* | integer | Take ID from getCountries. |
* Required parameter. In all requests also pass action=getNumbersStatus.
Example request
curl 'https://smscash.org/stubs/handler_api.php?action=getNumbersStatus&api_key=YOUR_API_KEY&country=86'package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://smscash.org/stubs/handler_api.php?action=getNumbersStatus&api_key=YOUR_API_KEY&country=86", nil)
if err != nil { panic(err) }
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil { panic(err) }
fmt.Println(resp.StatusCode, string(body))
}const response = await fetch("https://smscash.org/stubs/handler_api.php?action=getNumbersStatus&api_key=YOUR_API_KEY&country=86");
const result = await response.json();
console.log(response.status, result);import requests
response = requests.get(
"https://smscash.org/stubs/handler_api.php?action=getNumbersStatus&api_key=YOUR_API_KEY&country=86",
timeout=15,
)
print(response.status_code, response.json())Responses
{
"go_0": 0
}- The _0 suffix means a choice without a specific operator.
- Availability refers to the supplier’s overall pool. The selected channel is checked when a number is allocated.
GETgetStatusGet the latest code+
Easy request for session status and last SMS code. Leading zeros in the code are preserved.
Parameters
| Parameter | Type | Description |
|---|---|---|
api_key* | string | The user’s personal API key. |
id* | integer | ID of your session, received when the number was issued. |
* Required parameter. In all requests also pass action=getStatus.
Example request
curl 'https://smscash.org/stubs/handler_api.php?action=getStatus&api_key=YOUR_API_KEY&id=42'package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://smscash.org/stubs/handler_api.php?action=getStatus&api_key=YOUR_API_KEY&id=42", nil)
if err != nil { panic(err) }
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil { panic(err) }
fmt.Println(resp.StatusCode, string(body))
}const response = await fetch("https://smscash.org/stubs/handler_api.php?action=getStatus&api_key=YOUR_API_KEY&id=42");
const result = await response.text();
console.log(response.status, result);import requests
response = requests.get(
"https://smscash.org/stubs/handler_api.php?action=getStatus&api_key=YOUR_API_KEY&id=42",
timeout=15,
)
print(response.status_code, response.text)Responses
STATUS_WAIT_CODESTATUS_OK:001234STATUS_CANCELNO_ACTIVATION- Poll every 20 seconds. Reading a message again does not create another payment.
- After retry the old code is not returned: getStatus waits for the next SMS.
- After a number without SMS is deleted, getStatus and getSms return STATUS_CANCEL; getSmsFull returns the closed status, an empty phone and an empty sms list. REST /activations/{id} and /sms return 404 NO_ACTIVATION.
GETsetStatusManage session+
Finishes, cancels or resumes waiting for SMS. The session expiry stays the same.
Parameters
| Parameter | Type | Description |
|---|---|---|
api_key* | string | The user’s personal API key. |
id* | integer | ID of your session, received when the number was issued. |
status* | integer | 3 — wait for the next code without extending the session; 6 — finish after SMS; 8 — cancel immediately. |
* Required parameter. In all requests also pass action=setStatus.
Example request
curl 'https://smscash.org/stubs/handler_api.php?action=setStatus&api_key=YOUR_API_KEY&id=42&status=3' \
-H 'Idempotency-Key: request-unique-001'package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://smscash.org/stubs/handler_api.php?action=setStatus&api_key=YOUR_API_KEY&id=42&status=3", nil)
if err != nil { panic(err) }
req.Header.Set("Idempotency-Key", "request-unique-001")
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil { panic(err) }
fmt.Println(resp.StatusCode, string(body))
}const response = await fetch("https://smscash.org/stubs/handler_api.php?action=setStatus&api_key=YOUR_API_KEY&id=42&status=3", {
headers: {"Idempotency-Key": "request-unique-001"}
});
const result = await response.text();
console.log(response.status, result);import requests
response = requests.get(
"https://smscash.org/stubs/handler_api.php?action=setStatus&api_key=YOUR_API_KEY&id=42&status=3",
headers={"Idempotency-Key": "request-unique-001"},
timeout=15,
)
print(response.status_code, response.text)Responses
ACCESS_RETRY_GETACCESS_ACTIVATIONACCESS_CANCEL- Retry waits for the next code within the original 20 minutes. The issue and expiry times do not change.
- For status=3 use Idempotency-Key: repeating the request will not reset the new code already received. The history of SMS remains available.
- Cancellation does not remove rewards already earned.
- Only numbers with an SMS code are kept in history. Canceled and expired numbers without a code are deleted.
GETgetRepeatNumberIssue the same number again+
Opens a new session with a specific number from your history. You can select another available service in the same country.
Parameters
| Parameter | Type | Description |
|---|---|---|
api_key* | string | The user’s personal API key. |
number* | string | Your old number. Only numbers and an optional leading + are allowed. |
service* | string | Available service codes. The answer is limited to the area of the API key. |
session_duration | integer | The session lasts 20 minutes. Pass 20 or omit this parameter. |
with_operator | integer | 1 adds the operator ID to the response; 0 or omission returns three segments. |
ref | string | Public code of the software owner: 5% for him and 5% for the inviter. Without ref - 10% to the inviter. |
operator | string | Take ID from operators/getOperators (API). operator=1 · any/0 |
* Required parameter. In all requests also pass action=getRepeatNumber.
Example request
curl 'https://smscash.org/stubs/handler_api.php?action=getRepeatNumber&api_key=YOUR_API_KEY&number=380670000000&service=go' \
-H 'Idempotency-Key: request-unique-001'package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://smscash.org/stubs/handler_api.php?action=getRepeatNumber&api_key=YOUR_API_KEY&number=380670000000&service=go", nil)
if err != nil { panic(err) }
req.Header.Set("Idempotency-Key", "request-unique-001")
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil { panic(err) }
fmt.Println(resp.StatusCode, string(body))
}const response = await fetch("https://smscash.org/stubs/handler_api.php?action=getRepeatNumber&api_key=YOUR_API_KEY&number=380670000000&service=go", {
headers: {"Idempotency-Key": "request-unique-001"}
});
const result = await response.text();
console.log(response.status, result);import requests
response = requests.get(
"https://smscash.org/stubs/handler_api.php?action=getRepeatNumber&api_key=YOUR_API_KEY&number=380670000000&service=go",
headers={"Idempotency-Key": "request-unique-001"},
timeout=15,
)
print(response.status_code, response.text)Responses
ACCESS_NUMBER:43:380670000000NUMBER_IN_USE- First, end or cancel your current session. If the number is busy, re-issuance is not performed.
- The new session receives a new ID and the current tariff. Old SMS are not copied into it. ref is set again.
- SMScash allows repeating only numbers from the history of this account. The country is identified by number.
- The key of a deleted session remains used: replaying allocation with that key returns SESSION_CLOSED and does not issue another number.
GETgetSmsFullGet SMS as JSON+
Structured history of all messages with ID, sender, code, text and country, service and supplier data.
Parameters
| Parameter | Type | Description |
|---|---|---|
api_key* | string | The user’s personal API key. |
id* | integer | ID of your session, received when the number was issued. |
* Required parameter. In all requests also pass action=getSmsFull.
Example request
curl 'https://smscash.org/stubs/handler_api.php?action=getSmsFull&api_key=YOUR_API_KEY&id=42'package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://smscash.org/stubs/handler_api.php?action=getSmsFull&api_key=YOUR_API_KEY&id=42", nil)
if err != nil { panic(err) }
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil { panic(err) }
fmt.Println(resp.StatusCode, string(body))
}const response = await fetch("https://smscash.org/stubs/handler_api.php?action=getSmsFull&api_key=YOUR_API_KEY&id=42");
const result = await response.json();
console.log(response.status, result);import requests
response = requests.get(
"https://smscash.org/stubs/handler_api.php?action=getSmsFull&api_key=YOUR_API_KEY&id=42",
timeout=15,
)
print(response.status_code, response.json())Responses
{
"success": true,
"session_id": 42,
"phone": "380670000000",
"status": 1,
"status_name": "received",
"sms_count": 1,
"sms": [
{
"id": 101,
"external_id": "message-101",
"sender": "Service",
"code": "001234",
"text": "Код подтверждения: 001234",
"received_at": "2026-10-09T12:00:00Z",
"country": {
"id": 86,
"name": "Italy"
},
"service": {
"code": "go",
"name": "Google"
},
"provider": {
"id": 1,
"name": "Оператор 1"
}
}
],
"expires_at": "2026-10-09T12:20:00Z"
}- Preferred format for integration. Remember sms[].id to process only new messages.
- Numeric status SMScash: 1 - active, 6 - completed, 8 - canceled or expired. status_name distinguishes between waiting, received, finished, canceled, expired.
- Received codes remain available after a session closes. For large volumes, use REST /activations/{id}/sms with after_id.
- After a number without SMS is deleted, getStatus and getSms return STATUS_CANCEL; getSmsFull returns the closed status, an empty phone and an empty sms list. REST /activations/{id} and /sms return 404 NO_ACTIVATION.
GETgetSmsGet SMS as a text string+
Returns the entire SMS history in string format for existing clients.
Parameters
| Parameter | Type | Description |
|---|---|---|
api_key* | string | The user’s personal API key. |
id* | integer | ID of your session, received when the number was issued. |
* Required parameter. In all requests also pass action=getSms.
Example request
curl 'https://smscash.org/stubs/handler_api.php?action=getSms&api_key=YOUR_API_KEY&id=42'package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://smscash.org/stubs/handler_api.php?action=getSms&api_key=YOUR_API_KEY&id=42", nil)
if err != nil { panic(err) }
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil { panic(err) }
fmt.Println(resp.StatusCode, string(body))
}const response = await fetch("https://smscash.org/stubs/handler_api.php?action=getSms&api_key=YOUR_API_KEY&id=42");
const result = await response.text();
console.log(response.status, result);import requests
response = requests.get(
"https://smscash.org/stubs/handler_api.php?action=getSms&api_key=YOUR_API_KEY&id=42",
timeout=15,
)
print(response.status_code, response.text)Responses
STATUS_OK:2026-10-09T12:00:00Z|001234|Код подтверждения: 001234STATUS_WAIT_CODESTATUS_CANCEL- Message format: time|code|text. Multiple messages are separated by a colon.
- The text SMS itself may contain colons and vertical bars. For reliable parsing, use getSmsFull.
GETgetServicesServices+
Available service codes. The answer is limited to the area of the API key.
Parameters
| Parameter | Type | Description |
|---|---|---|
api_key* | string | The user’s personal API key. |
country | integer | Take ID from getCountries. |
* Required parameter. In all requests also pass action=getServices.
Example request
curl 'https://smscash.org/stubs/handler_api.php?action=getServices&api_key=YOUR_API_KEY'package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://smscash.org/stubs/handler_api.php?action=getServices&api_key=YOUR_API_KEY", nil)
if err != nil { panic(err) }
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil { panic(err) }
fmt.Println(resp.StatusCode, string(body))
}const response = await fetch("https://smscash.org/stubs/handler_api.php?action=getServices&api_key=YOUR_API_KEY");
const result = await response.json();
console.log(response.status, result);import requests
response = requests.get(
"https://smscash.org/stubs/handler_api.php?action=getServices&api_key=YOUR_API_KEY",
timeout=15,
)
print(response.status_code, response.json())Responses
{
"go": {
"name": "Google",
"code": "go"
}
}- The service directory is shared across the supplier. Number availability is checked separately.
GETgetCountriesCountries+
IDs, names and calling codes for countries in the selected channel.
Parameters
| Parameter | Type | Description |
|---|---|---|
api_key* | string | The user’s personal API key. |
* Required parameter. In all requests also pass action=getCountries.
Example request
curl 'https://smscash.org/stubs/handler_api.php?action=getCountries&api_key=YOUR_API_KEY'package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://smscash.org/stubs/handler_api.php?action=getCountries&api_key=YOUR_API_KEY", nil)
if err != nil { panic(err) }
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil { panic(err) }
fmt.Println(resp.StatusCode, string(body))
}const response = await fetch("https://smscash.org/stubs/handler_api.php?action=getCountries&api_key=YOUR_API_KEY");
const result = await response.json();
console.log(response.status, result);import requests
response = requests.get(
"https://smscash.org/stubs/handler_api.php?action=getCountries&api_key=YOUR_API_KEY",
timeout=15,
)
print(response.status_code, response.json())Responses
{
"86": {
"id": 86,
"name": "Italy",
"phone_code": "39"
}
}GETgetOperatorsOperators+
Available operators: API ID, name, and hold period.
Parameters
| Parameter | Type | Description |
|---|---|---|
api_key* | string | The user’s personal API key. |
country | integer | Take ID from getCountries. |
operator | string | Take ID from operators/getOperators (API). operator=1 · any/0 |
* Required parameter. In all requests also pass action=getOperators.
Example request
curl 'https://smscash.org/stubs/handler_api.php?action=getOperators&api_key=YOUR_API_KEY'package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://smscash.org/stubs/handler_api.php?action=getOperators&api_key=YOUR_API_KEY", nil)
if err != nil { panic(err) }
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil { panic(err) }
fmt.Println(resp.StatusCode, string(body))
}const response = await fetch("https://smscash.org/stubs/handler_api.php?action=getOperators&api_key=YOUR_API_KEY");
const result = await response.json();
console.log(response.status, result);import requests
response = requests.get(
"https://smscash.org/stubs/handler_api.php?action=getOperators&api_key=YOUR_API_KEY",
timeout=15,
)
print(response.status_code, response.json())Responses
{
"1": {
"id": 1,
"provider_id": 1,
"operator": 1,
"name": "Оператор 1",
"earnings_hold_days": 45
}
}- Take ID from operators/getOperators (API).
GETgetRewardsReward for SMS+
Rates depend on the country. All table amounts are per paid SMS.
Parameters
| Parameter | Type | Description |
|---|---|---|
api_key* | string | The user’s personal API key. |
country | integer | Take ID from getCountries. |
service | string | Available service codes. The answer is limited to the area of the API key. |
operator | string | Take ID from operators/getOperators (API). operator=1 · any/0 |
* Required parameter. In all requests also pass action=getRewards.
Example request
curl 'https://smscash.org/stubs/handler_api.php?action=getRewards&api_key=YOUR_API_KEY&country=59&service=vi'package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://smscash.org/stubs/handler_api.php?action=getRewards&api_key=YOUR_API_KEY&country=59&service=vi", nil)
if err != nil { panic(err) }
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil { panic(err) }
fmt.Println(resp.StatusCode, string(body))
}const response = await fetch("https://smscash.org/stubs/handler_api.php?action=getRewards&api_key=YOUR_API_KEY&country=59&service=vi");
const result = await response.json();
console.log(response.status, result);import requests
response = requests.get(
"https://smscash.org/stubs/handler_api.php?action=getRewards&api_key=YOUR_API_KEY&country=59&service=vi",
timeout=15,
)
print(response.status_code, response.json())Responses
{
"59": {
"vi": {
"1": "0.01000000",
"3": "0.00500000"
}
}
}{}- USD tariff amounts are returned as exact decimal strings with 8 decimal places:
- Enabled providers available to your key.
- country ID → service code → operator ID → reward (USD)
GETgetBalanceUser balance+
Addition SMScash: available balance taking into account accruals, referral bonuses and payment requests.
Parameters
| Parameter | Type | Description |
|---|---|---|
api_key* | string | The user’s personal API key. |
* Required parameter. In all requests also pass action=getBalance.
Example request
curl 'https://smscash.org/stubs/handler_api.php?action=getBalance&api_key=YOUR_API_KEY'package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://smscash.org/stubs/handler_api.php?action=getBalance&api_key=YOUR_API_KEY", nil)
if err != nil { panic(err) }
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil { panic(err) }
fmt.Println(resp.StatusCode, string(body))
}const response = await fetch("https://smscash.org/stubs/handler_api.php?action=getBalance&api_key=YOUR_API_KEY");
const result = await response.text();
console.log(response.status, result);import requests
response = requests.get(
"https://smscash.org/stubs/handler_api.php?action=getBalance&api_key=YOUR_API_KEY",
timeout=15,
)
print(response.status_code, response.text)Responses
ACCESS_BALANCE:0.00- getBalance returns the available USD balance with up to 8 decimal places.
- Only funds whose hold period has ended can be withdrawn.
GETgetHoldBalanceOn hold+
After an SMS is received, its earnings are held for the supplier's specified period. On the scheduled date, the amount automatically becomes available to withdraw.
Parameters
| Parameter | Type | Description |
|---|---|---|
api_key* | string | The user’s personal API key. |
* Required parameter. In all requests also pass action=getHoldBalance.
Example request
curl 'https://smscash.org/stubs/handler_api.php?action=getHoldBalance&api_key=YOUR_API_KEY'package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://smscash.org/stubs/handler_api.php?action=getHoldBalance&api_key=YOUR_API_KEY", nil)
if err != nil { panic(err) }
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil { panic(err) }
fmt.Println(resp.StatusCode, string(body))
}const response = await fetch("https://smscash.org/stubs/handler_api.php?action=getHoldBalance&api_key=YOUR_API_KEY");
const result = await response.text();
console.log(response.status, result);import requests
response = requests.get(
"https://smscash.org/stubs/handler_api.php?action=getHoldBalance&api_key=YOUR_API_KEY",
timeout=15,
)
print(response.status_code, response.text)Responses
ACCESS_HOLD_BALANCE:34.50000001- SMScash · getHoldBalance · USD · 8
- Only funds whose hold period has ended can be withdrawn.
Response codes and repeat requests
In handler_api.php business outcomes usually come with HTTP 200. Check the body text. Directories and getSmsFull return JSON if successful; errors are always text.
| Code | HTTP | Cause and next step |
|---|---|---|
TARIFF_NOT_CONFIGURED | 200 | Rates are not set yetNumber allocation will start once SMS rewards are configured. |
COUNTRY_BLOCKED | 200 | Number allocation for this country is blocked.Choose another country. |
BAD_SERVICE | 200 | Number allocation for this service is blocked.Choose another service. |
PROVIDER_NOT_READY | 200 | Number allocation is temporarily unavailableRefresh the API catalogs. |
BAD_KEY | 400 | No api_key or invalid format.Check the key in the request. |
INVALID_API_KEY | 401 | The key is unknown, revoked or the account is disabled.Create a valid API key. |
BAD_COUNTRY | 400 | country is missing or not a positive number.Take ID from getCountries. |
BAD_SESSION_DURATION | 400 | Phone numbers are issued for exactly 20 minutes.Correct session_duration. |
BAD_REQUEST | 400 | Invalid parameter or Idempotency-Key.Please correct your request. |
BAD_SERVICE / BAD_OPERATOR / INVALID_PROVIDER | 200 | Unknown or disabled directory item.Refresh the API catalogs. |
BAD_NUMBER | 200 | Incorrect number format.Give the number in digits. |
BAD_ACTION / BAD_STATUS | 200 | Unknown command, ID or operation.Check the settings. |
EMPTY_POOL | 200 | No matching phone numbers are currently available.Repeat after 10-30 seconds or change filters. |
NUMBER_IN_USE | 200 | A specific number is occupied by an active session.End your session or select another number. |
NO_ACTIVATION | 200 | The session or previous number does not belong to your account.Check ID and key. |
SESSION_CLOSED / SMS_REQUIRED | 200 | State transition is currently unavailable.Check the condition and availability of SMS. |
SCOPE_BLOCKED | 200 | The service, country, or vendor is not authorized for the key.Update the API key's scope. |
IDEMPOTENCY_CONFLICT | 200 | This query key is already associated with other parameters.For a new operation, create another Idempotency-Key. |
BAD_REF / SELF_REF | 400 | The software code is unknown, disabled, or belongs to the user himself.Pass on the software owner's code. |
INTERNAL_ERROR | 500 | Temporary server or vendor error.Repeat with a delay and the same Idempotency-Key. |
ALLOCATION_PENDING | 200 | Number allocation is already in progress. Retry with the same Idempotency-Key.Number allocation is already in progress. Retry with the same Idempotency-Key. |
ALLOCATION_UNCERTAIN | 200 | The allocation result is unconfirmed. Automatic retry is disabled to avoid allocating a second number.The allocation result is unconfirmed. Automatic retry is disabled to avoid allocating a second number. |
REST returns an object {"error":{"code":"…","message":"…"}} and regular HTTP statuses 400/401/403/404/409/503.
{
"error": {
"code": "BAD_REQUEST",
"message": "Check the request fields.",
"request_id": "req_…",
"hint": "Use the documented JSON type; numbers must not be quoted.",
"retryable": false,
"details": {
"field": "country",
"expected": "integer"
}
}
}X-Request-ID: included in every API response
405: Allow lists the supported HTTP methods
ALLOCATION_PENDING: retryable=true · Retry-After=3 · same operation key
ALLOCATION_UNCERTAIN: retryable=false · contact support
Transport errors: check the operation before another write; keep the original key.REST for new integrations
USD tariff amounts are returned as exact decimal strings with 8 decimal places: 0.00300000 USD.
The balance currency is USD. Request and response schemas are available in OpenAPI.
/api/v1/catalogServices and countries/api/v1/tariffsSMS reward rates by country/api/v1/offersRates and rewards/api/v1/servicesDirectory/api/v1/countriesDirectory/api/v1/operatorsDirectory/api/v1/availability?country=1Number availability/api/v1/activationsNew session/api/v1/activations/batch?ids=42,43Check multiple numbers/api/v1/activationsLatest 200 sessions: scope=history, waiting or all/api/v1/activations/{id}Session and messages/api/v1/activations/{id}/sms?after_id=0&limit=100New SMS with cursor/api/v1/activations/{id}/retryWaiting for SMS/api/v1/activations/{id}/finishCompletion/api/v1/activations/{id}/cancelCancel/api/v1/activations/repeatNumber reissue/api/v1/keysAPI keys/api/v1/keysCreate a key/api/v1/keys/{id}Change name or policy/api/v1/keys/{id}Revoke key/api/v1/referralsReferral code and earnings/api/v1/summaryBalance and Summary/api/v1/balanceOn hold/api/v1/ledgerEarnings ledger/api/v1/withdrawalsPayout requests/api/v1/withdrawalsCreate a request/api/v1/statisticsOverall statistics/api/v1/earnings/holdsEarnings holdReceiving only new SMS
GET /api/v1/activations/42/sms?after_id=0&limit=100
Authorization: Bearer YOUR_API_KEY{
"session_id": 42,
"sms": [
{
"id": 101,
"code": "001234",
"text": "Code: 001234",
"sender": "Service",
"received_at": "2026-10-09T12:00:00Z"
}
],
"next_cursor": 101,
"has_more": false
}Save next_cursor and pass it on as after_id. If has_more=true, the next page can be read immediately. limit: 1–200. Sessions and SMS are available only to the owner.