BEE-SMS — SMS Activate Compatible API
This is a byte-compatible implementation of the SMS Activate protocol. If your software already talks to a HeroSMS / SMS-Activate endpoint (.../stubs/handler_api.php), you can switch to BEE-SMS by only changing the base URL — no code changes required.
Protocol Description
All requests go to https://api.bee-sms.com/stubs/handler_api.php
- It is a single endpoint; the operation is selected by the
actionquery parameter. - Authentication uses the
api_keyquery parameter — this is your API Token (the same token used by the OTP API). - Responses are either plain text (e.g.
ACCESS_NUMBER:...) or JSON, depending on the action (theV2actions and the list/price actions return JSON). - Most actions return HTTP 200 and carry business errors in the response body (a text error code, or a JSON
{ title, details, info }object), exactly as in SMS-Activate. The three rich JSON actions — getNumberV2, getStatusV2 and getActiveActivations — instead return hero's real HTTP status code (400/401/402/403/404/422/500) on error; see each action's "Errors" table.
Common parameters
| Field | Location | Type | Required | Description |
|---|---|---|---|---|
| api_key | query | String | Yes | Your API Token (from the profile page) |
| action | query | String | Yes | The operation name (see each section below) |
Country & service codes
The country parameter is the SMS-Activate numeric country id (e.g. 2 = Kazakhstan, 16 = United Kingdom, 187 = USA). The service parameter is the short service code (e.g. tg = Telegram, wa = WhatsApp). Only the countries and services BEE-SMS actually carries are available, and a few codes may differ from other providers — always call getPrices to discover the exact country ids, service codes, prices and availability you can use.
Browse the exact ids and codes BEE-SMS currently carries — these are the values to pass as country and service (the same lists are returned by getCountries / getServicesList below):
List country code
List service code
Pricing shown by this API is the price after your account discount — the same amount that will be charged when you buy a number. All money values are in your account currency (USD), and
currencyis the ISO-4217 numeric code840.
Affiliate / referral
Commissions work the same as the OTP API. Sign up, then your account-level referral applies automatically. More details.
getBalance
Returns the account balance.
GET - https://api.bee-sms.com/stubs/handler_api.php?api_key=$api_key&action=getBalance
Response — text/plain
ACCESS_BALANCE:109.78
The number is your balance in your account currency (USD).
Possible errors (text/plain)
BAD_KEY
getNumber
Buys a number for a service in a country. Returns the activation id and phone number as plain text.
GET - https://api.bee-sms.com/stubs/handler_api.php?api_key=$api_key&action=getNumber&service=$service&country=$country
Parameters
| Field | Location | Type | Required | Description |
|---|---|---|---|---|
| service | query | String | Yes | Short service code (e.g. tg) |
| country | query | Number | Yes | SMS-Activate numeric country id (e.g. 2) |
| maxPrice | query | Number | No | Do not buy if the price exceeds this value (in your currency, e.g. 1.50) |
| fixedPrice | query | Number | No | Alias of maxPrice, used only when maxPrice is not provided |
| ref | query | String | No | Referral id |
operatorandphoneException(SMS-Activate parameters) are accepted for client compatibility but ignored — BEE-SMS does not support operator selection or prefix exclusion.
Response — text/plain
ACCESS_NUMBER:2541517119212500009:79001234567
Format: ACCESS_NUMBER:{activationId}:{phoneNumber} (the phone number includes the country dialing code, without +).
Possible errors (text/plain)
BAD_SERVICE
NO_NUMBERS
NO_BALANCE
WRONG_MAX_PRICE:0.2
BANNED:2026-06-13T10:30:45Z
CHANNELS_LIMIT
WRONG_MAX_PRICE:{min}returns the current price you must accept (decimal, trailing zeros stripped — e.g.0.2, not0.20); ifmaxPricecannot be parsed, the bare codeWRONG_MAX_PRICEis returned.BANNEDis returned bare when the account is disabled, or asBANNED:{datetime}(format illustrative) when access to a specific service is temporarily restricted. Any action may also returnSERVER_ERRORon a transient failure.
getNumberV2
Same as getNumber but returns a JSON object with full activation details.
GET - https://api.bee-sms.com/stubs/handler_api.php?api_key=$api_key&action=getNumberV2&service=$service&country=$country
Parameters
| Field | Location | Type | Required | Description |
|---|---|---|---|---|
| service | query | String | Yes | Short service code (e.g. tg) |
| country | query | Number | Yes | SMS-Activate numeric country id (e.g. 2) |
| maxPrice | query | Number | No | Do not buy if the price exceeds this value (in your currency, e.g. 1.50) |
| fixedPrice | query | Number | No | Alias of maxPrice, used only when maxPrice is not provided |
| ref | query | String | No | Referral id |
operatorandphoneException(SMS-Activate parameters) are accepted for client compatibility but ignored — BEE-SMS does not support operator selection or prefix exclusion.
Response — application/json
| Field | Type | Description |
|---|---|---|
| activationId | String | Activation / order id |
| phoneNumber | String | Phone number (with dialing code, no +) |
| activationCost | Number | Price charged, in your currency (after discount) |
| currency | Number | ISO-4217 numeric currency code (always 840 = USD) |
| countryCode | Number | SMS-Activate numeric country id |
| countryPhoneCode | Number | Country dialing code |
| canGetAnotherSms | Boolean | Whether another SMS can be requested for this number |
| activationTime | String | Activation start time (UTC, yyyy-MM-dd'T'HH:mm:ss'Z') |
| activationEndTime | String | Activation end time (UTC) |
| activationOperator | String | Operator (may be empty) |
Success
{
"activationId": "2541517119212500009",
"phoneNumber": "79001234567",
"activationCost": 0.2,
"currency": 840,
"countryCode": 2,
"countryPhoneCode": 7,
"canGetAnotherSms": true,
"activationTime": "2026-06-13T10:30:45Z",
"activationEndTime": "2026-06-13T10:50:45Z",
"activationOperator": ""
}
Errors (application/json)
Unlike the text actions, getNumberV2 returns hero's real HTTP status code plus a
{ title, details, info } body. Each error case:
| HTTP | title | details | info |
|---|---|---|---|
| 400 | WRONG_MAX_PRICE | The maximum price is less than the permitted price | { "min": 0.2 } (the price you must accept) |
| 401 | BAD_KEY | Unauthorized | {} |
| 402 | NO_BALANCE | Payment Required | {} |
| 403 | BANNED | Account is banned | {} |
| 403 | CHANNELS_LIMIT | You have reached the maximum number of concurrent threads (purchases) allowed for your account. Contact the technical support. | { "current_threads": 0, "max_allowed": -1 } |
| 422 | UNPROCESSABLE_ENTITY | Validation failed | { "field": "service", "code": "REQUIRED", "message": "Param 'service' is required." } |
| 500 | SERVER_ERROR | Server Gone | {} |
A missing required parameter returns
422withinfo.code = "REQUIRED"; an unknown country id or service code returns422withinfo.code = "INVALID". When the catalogue has no numbers for the requested service, getNumberV2 returns HTTP 200 with{ "title": "NO_NUMBERS", "details": "no numbers available", "info": {} }.
// 403 — concurrency cap reached
{
"title": "CHANNELS_LIMIT",
"details": "You have reached the maximum number of concurrent threads (purchases) allowed for your account. Contact the technical support.",
"info": {
"current_threads": 0,
"max_allowed": -1
}
}
setStatus
Changes the status of an activation.
GET - https://api.bee-sms.com/stubs/handler_api.php?api_key=$api_key&action=setStatus&id=$id&status=$status
Parameters
| Field | Location | Type | Required | Description |
|---|---|---|---|---|
| id | query | String | Yes | Activation id |
| status | query | Number | Yes | New status (see table below) |
Status values & responses — text/plain
| status | Meaning | Response |
|---|---|---|
| 1 | Ready to receive SMS | ACCESS_READY |
| 3 | Request another SMS | ACCESS_RETRY_GET |
| 6 | Complete activation | ACCESS_ACTIVATION |
| 8 | Cancel (full refund) | ACCESS_CANCEL |
BEE-SMS does not have a separate "resend" state, so status
1and3are accepted as no-ops (returning the expectedACCESS_READY/ACCESS_RETRY_GET). Status8is idempotent: cancelling an already-closed activation will not refund twice.
Possible errors (text/plain)
BAD_STATUS
NO_ACTIVATION
getStatus
Returns the current status (and code, once received) of an activation as plain text.
GET - https://api.bee-sms.com/stubs/handler_api.php?api_key=$api_key&action=getStatus&id=$id
Parameters
| Field | Location | Type | Required | Description |
|---|---|---|---|---|
| id | query | String | Yes | Activation id |
Responses — text/plain
| Response | Meaning |
|---|---|
STATUS_WAIT_CODE | Waiting for the SMS |
STATUS_OK:{code} | Code received (code appended) |
STATUS_CANCEL | Activation cancelled / timed out |
Possible errors (text/plain)
NO_ACTIVATION
getStatusV2
Same as getStatus but returns a JSON object.
GET - https://api.bee-sms.com/stubs/handler_api.php?api_key=$api_key&action=getStatusV2&id=$id
Parameters — identical to getStatus.
Response — application/json
verificationType: 0 = SMS (BEE-SMS supports SMS only). sms.code is the parsed code; sms.text is the full message text. call is always null.
Success
{
"verificationType": 0,
"sms": {
"dateTime": "2026-06-13T10:35:12Z",
"code": "429916",
"text": "Your verification code is 429916"
},
"call": null
}
Errors (application/json)
Like getNumberV2, getStatusV2 returns hero's real HTTP status code plus a
{ title, details, info } body:
| HTTP | title | details | info |
|---|---|---|---|
| 400 | BAD_STATUS | Wrong status code | {} |
| 401 | BAD_KEY | Unauthorized | {} |
| 402 | NO_BALANCE | Payment Required | {} |
| 403 | BANNED | Account is banned | {} |
| 403 | CHANNELS_LIMIT | You have reached the maximum number of concurrent threads (purchases) allowed for your account. Contact the technical support. | { "current_threads": 0, "max_allowed": -1 } |
| 404 | NOT_FOUND | Activation Not Found | {} |
| 422 | UNPROCESSABLE_ENTITY | Validation failed | { "field": "id", "code": "REQUIRED", "message": "Param 'id' is required." } |
| 500 | SERVER_ERROR | Server Gone | {} |
// 404 — the activation id does not exist for this account
{
"title": "NOT_FOUND",
"details": "Activation Not Found",
"info": {}
}
getActiveActivations
Returns the list of the account's currently active (waiting) activations.
GET - https://api.bee-sms.com/stubs/handler_api.php?api_key=$api_key&action=getActiveActivations
Parameters
| Field | Location | Type | Required | Description |
|---|---|---|---|---|
| start | query | Number | No | Offset (default 0) |
| limit | query | Number | No | Page size, max 100 (default 100) |
Response — application/json
data[] columns:
| Field | Type | Description |
|---|---|---|
| activationId | String | Activation id |
| serviceCode | String | Short service code |
| phoneNumber | String | Phone number (with dialing code) |
| activationCost | Number | Price charged (after discount) |
| activationStatus | String | Activation status |
| smsCode | String | Parsed code (may be null) |
| smsText | String | Full SMS text (may be null) |
| activationTime | String | Activation start time (UTC) |
| discount | String | Discount applied |
| repeated | String | Whether this is a reused number |
| countryCode | String | SMS-Activate numeric country id |
| countryName | String | Country name |
| canGetAnotherSms | String | Whether another SMS can be requested |
| currency | String | ISO-4217 numeric currency code (840) |
Success
{
"status": "success",
"data": [
{
"activationId": "2541517119212500009",
"serviceCode": "tg",
"phoneNumber": "79001234567",
"activationCost": 0.2,
"activationStatus": "waiting",
"smsCode": null,
"smsText": null,
"activationTime": "2026-06-13T10:30:45Z",
"discount": "",
"repeated": "false",
"countryCode": "2",
"countryName": "Kazakhstan",
"canGetAnotherSms": "true",
"currency": "840"
}
]
}
When there are no active activations, the response is a normal empty success (HTTP 200):
{
"status": "success",
"data": []
}
Errors (application/json)
Like getStatusV2, getActiveActivations returns hero's real HTTP status code plus a
{ title, details, info } body for the failure cases:
| HTTP | title | details | info |
|---|---|---|---|
| 401 | BAD_KEY | Unauthorized | {} |
| 402 | NO_BALANCE | Payment Required | {} |
| 403 | BANNED | Account is banned | {} |
| 403 | CHANNELS_LIMIT | You have reached the maximum number of concurrent threads (purchases) allowed for your account. Contact the technical support. | { "current_threads": 0, "max_allowed": -1 } |
| 500 | SERVER_ERROR | Server Gone | {} |
getPrices
Returns prices and available quantity, grouped by country id and service code. Call this to discover which country ids and service codes you can use.
GET - https://api.bee-sms.com/stubs/handler_api.php?api_key=$api_key&action=getPrices&country=$country&service=$service
Parameters
| Field | Location | Type | Required | Description |
|---|---|---|---|---|
| country | query | Number | No | SMS-Activate numeric country id (filter) |
| service | query | String | No | Short service code (filter) |
Response — application/json
A nested object { "<countryId>": { "<serviceCode>": { cost, count, physicalCount } } }:
| Field | Type | Description |
|---|---|---|
| cost | Number | Price (after your discount) |
| count | Number | Available quantity |
| physicalCount | Number | Available physical quantity (currently always equals count) |
Success
{
"2": {
"tg": {
"cost": 0.2,
"count": 1500,
"physicalCount": 1500
}
}
}
Possible Errors (application/json)
{
"title": "BAD_SERVICE",
"details": "service is invalid",
"info": {}
}
getCountries
Returns the countries BEE-SMS carries, keyed by SMS-Activate numeric country id. Call it to discover the country ids accepted by getNumber / getPrices; only supported countries are listed.
GET - https://api.bee-sms.com/stubs/handler_api.php?api_key=$api_key&action=getCountries
Response — application/json
An object keyed by country id; each value carries the id and localized names (rus, eng, chn):
{
"2": {
"id": 2,
"rus": "Казахстан",
"eng": "Kazakhstan",
"chn": "哈萨克斯坦"
},
"187": {
"id": 187,
"rus": "США",
"eng": "USA",
"chn": "美国(物理)"
}
}
getServicesList
Returns the services BEE-SMS carries. Call it to discover the service codes accepted by getNumber / getPrices; only supported services are listed.
GET - https://api.bee-sms.com/stubs/handler_api.php?api_key=$api_key&action=getServicesList
Response — application/json
| Field | Type | Description |
|---|---|---|
| status | String | Always "success" |
| services | Array | List of { code, name } |
| services.code | String | Short service code |
| services.name | String | Service display name |
{
"status": "success",
"services": [
{
"code": "go",
"name": "Google,youtube,Gmail"
},
{
"code": "wa",
"name": "Whatsapp"
}
]
}
Error reference
Text actions (getNumber, getBalance, setStatus, getStatus) return a bare error code string at HTTP 200. The list/price JSON actions (getPrices, getCountries, getServicesList) return { title, details, info } at HTTP 200. The three rich JSON actions (getNumberV2, getStatusV2, getActiveActivations) return { title, details, info } with hero's real HTTP status code — see each action's "Errors" table for the exact status/title/info per case.
The per-action error lists above show the most common cases; in addition, any action may return NO_KEY / BAD_KEY (authentication), BAD_ACTION (unknown action) or SERVER_ERROR (transient failure). The code names below are the text-action wire codes; on the rich JSON actions the same conditions map to the titles/status codes in their "Errors" tables (e.g. text BAD_SERVICE → JSON 422 UNPROCESSABLE_ENTITY, text NO_ACTIVATION → JSON 404 NOT_FOUND).
| Code | Meaning |
|---|---|
NO_KEY | api_key is missing |
BAD_KEY | api_key is invalid |
BAD_ACTION | Unknown action |
BAD_SERVICE | Unknown service or country |
BAD_STATUS | Invalid setStatus value |
NO_NUMBERS | No numbers available |
NO_BALANCE | Insufficient balance |
NO_ACTIVATION | Activation not found (JSON getStatusV2 → 404 NOT_FOUND) |
WRONG_MAX_PRICE:{p} | Your maxPrice is below the current price {p} |
BANNED:{datetime} | Access to this service is restricted until {datetime} |
CHANNELS_LIMIT | Too many pending activations — receive or cancel some |
SERVER_ERROR | Temporary server error — retry later |