Python SDK for the VirtualSMS Consumer API — SMS verification, phone number rental, and activation management.
Project description
VirtualSMS Python SDK
Python SDK for the VirtualSMS Consumer API — SMS verification, phone number rental, and activation management.
Requirements
- Python 3.9 or higher
- No external dependencies (uses standard library only)
Installation
pip install virtualsmslabs-python-sdk
Quick Start
from virtualsms import VirtualSMSClient, ActivationStatus
client = VirtualSMSClient("YOUR_API_KEY", "https://api.virtualsms.de")
# Check balance
balance = client.get_balance()
print(f"Balance: ${balance.balance:.2f}")
# Order a WhatsApp number in Brazil
number = client.get_number("wa", 73, max_price=2.00)
print(f"Number: {number.phone_number} (ID: {number.activation_id})")
# Set status to ready (SMS sent)
client.set_status(number.activation_id, ActivationStatus.READY)
# Poll for SMS code
status = client.get_status(number.activation_id)
if status.code is not None:
print(f"SMS code: {status.code}")
# Complete the activation
client.set_status(number.activation_id, ActivationStatus.COMPLETE)
API Reference
Client Constructor
client = VirtualSMSClient(
api_key="YOUR_API_KEY", # Your API key (required)
base_url="https://api.virtualsms.de", # API base URL (optional)
transport=None, # Optional custom transport
)
Methods
Account
get_balance() -> BalanceResponse
Returns the current account balance.
balance = client.get_balance()
print(balance.balance) # 10.50
Information & Pricing
get_countries(pool_provider=None) -> dict
Returns all available countries.
get_services_list(country=None, lang=None) -> dict
Returns available services for a country.
get_operators(country, pool_provider=None) -> list
Returns available mobile operators for a country.
get_prices(service=None, country=None, pool_provider=None) -> dict
Returns pricing data organized by country and service.
get_prices_extended(service=None, country=None, free_price=None, pool_provider=None) -> dict
Returns extended pricing with price tiers.
get_prices_verification(service=None, pool_provider=None) -> dict
Returns pricing in inverted format (service → country).
get_numbers_status(country, operator=None, pool_provider=None) -> dict
Returns available phone quantity per service.
get_top_countries_by_service(service) -> list
Returns top 10 countries for a service, ranked by purchase share and success rate.
Ordering Numbers
get_number(service, country, **options) -> NumberResponse
Orders a phone number. Returns text format response.
number = client.get_number(
service="wa",
country=73,
max_price=2.00,
operator="claro",
forward=True,
)
print(number.activation_id) # 123
print(number.phone_number) # 447777777777
Options:
| Parameter | Type | Description |
|---|---|---|
max_price |
float |
Maximum price willing to pay |
operator |
str |
Mobile operator filter |
phone_exception |
str |
Phone prefixes to exclude (comma-separated) |
forward |
bool |
Enable call forwarding |
activation_type |
int |
Activation type: 0=SMS, 1=number, 2=voice |
language |
str |
Language for voice activation |
use_cashback |
bool |
Use cashback balance first |
user_id |
str |
End-user ID for tracking |
ref |
str |
Referral ID |
pool_provider |
str |
Pool provider: alpha, prime, gamma, zeta |
get_number_v2(service, country, **options) -> dict
Same as get_number but returns JSON with additional fields. Supports order_id for idempotency.
Activation Management
set_status(id, status) -> str
Changes activation status.
from virtualsms import ActivationStatus
client.set_status(activation_id, ActivationStatus.READY) # 1 - SMS sent
client.set_status(activation_id, ActivationStatus.RETRY) # 3 - Request another SMS
client.set_status(activation_id, ActivationStatus.COMPLETE) # 6 - Finish
client.set_status(activation_id, ActivationStatus.CANCEL) # 8 - Cancel
get_status(id) -> StatusResponse
Returns activation status in text format.
status = client.get_status(activation_id)
print(status.status) # STATUS_OK, STATUS_WAIT_CODE, STATUS_CANCEL
print(status.code) # 123456 (None if not yet received)
get_status_v2(id) -> dict
Returns activation status in JSON format with SMS/call details.
get_active_activations() -> list
Returns all currently active activations.
check_extra_activation(id) -> dict
Checks if a number is available for reactivation.
get_extra_activation(id) -> NumberResponse
Creates an extra activation on a previously used number.
Notifications
get_notifications() -> dict
Returns user notifications including penalties, low balance alerts, and admin messages.
Constants
ActivationStatus
ActivationStatus.READY # 1 - SMS has been sent to the number
ActivationStatus.RETRY # 3 - Request another SMS code
ActivationStatus.COMPLETE # 6 - Finish activation
ActivationStatus.CANCEL # 8 - Cancel activation
PoolProvider
PoolProvider.ALPHA # 'alpha'
PoolProvider.PRIME # 'prime'
PoolProvider.GAMMA # 'gamma'
PoolProvider.ZETA # 'zeta'
Error Handling
The SDK raises typed exceptions for all API errors. Each error code maps to a specific exception class:
from virtualsms import (
VirtualSMSClient,
VirtualSMSException,
AuthenticationException,
InsufficientBalanceException,
NoNumbersException,
ValidationException,
ActivationException,
RateLimitException,
ServerException,
)
try:
number = client.get_number("wa", 73)
except AuthenticationException:
# BAD_KEY, BANNED, PURCHASE_RESTRICTED, SERVICE_RESTRICTED
pass
except InsufficientBalanceException:
# NO_BALANCE
pass
except NoNumbersException:
# NO_NUMBERS
pass
except ValidationException:
# WRONG_SERVICE, WRONG_COUNTRY, BAD_ACTION, BAD_STATUS, NO_PRICES, INVALID_PROVIDER
pass
except ActivationException:
# NO_ACTIVATION, WRONG_ACTIVATION_ID, EARLY_CANCEL_DENIED, RENEW_ACTIVATION_NOT_AVAILABLE
pass
except RateLimitException as e:
# CONCURRENT_LIMIT — check e.retry_after
pass
except ServerException:
# ERROR_SQL, unknown errors
pass
Error Code Reference
| Error Code | Exception | Description |
|---|---|---|
BAD_KEY |
AuthenticationException |
Invalid API key |
BANNED |
AuthenticationException |
Account banned or IP blocked |
PURCHASE_RESTRICTED |
AuthenticationException |
User restricted from purchasing |
SERVICE_RESTRICTED |
AuthenticationException |
Service restricted for account |
NO_BALANCE |
InsufficientBalanceException |
Insufficient balance |
NO_NUMBERS |
NoNumbersException |
No numbers available |
WRONG_SERVICE |
ValidationException |
Invalid service code |
WRONG_COUNTRY |
ValidationException |
Invalid country ID |
BAD_ACTION |
ValidationException |
Invalid action |
BAD_STATUS |
ValidationException |
Invalid status code |
NO_PRICES |
ValidationException |
No pricing data available |
INVALID_PROVIDER |
ValidationException |
Invalid pool provider |
NO_ACTIVATION |
ActivationException |
Activation not found |
WRONG_ACTIVATION_ID |
ActivationException |
Invalid activation ID |
EARLY_CANCEL_DENIED |
ActivationException |
Cannot cancel within 5 minutes |
RENEW_ACTIVATION_NOT_AVAILABLE |
ActivationException |
Number not available for reactivation |
CONCURRENT_LIMIT |
RateLimitException |
Too many concurrent activations |
ERROR_SQL |
ServerException |
Internal server error |
Tracking Headers
The SDK sends anonymous tracking headers with every request for analytics and debugging:
| Header | Value | Privacy |
|---|---|---|
X-SDK-Version |
1.0.0 |
SDK version string |
X-SDK-Language |
python |
SDK language |
X-SDK-Machine-Id |
SHA-256 hash of platform.platform() + sys.implementation.name (truncated to 32 chars) |
Irreversible hash — no hostname or IP exposed |
X-SDK-Timestamp |
ISO 8601 UTC timestamp | Request time |
No personally identifiable information is transmitted. The machine ID is a one-way hash and cannot be reversed to identify the source machine.
Custom Transport
By default, the SDK uses urllib.request for HTTP requests. You can provide your own transport implementation:
from virtualsms import VirtualSMSClient, Transport, Response
class MyTransport(Transport):
def send(self, url: str, headers: dict) -> Response:
# Your HTTP implementation
return Response(status_code=200, body="ACCESS_BALANCE:10.50")
client = VirtualSMSClient("API_KEY", "https://api.example.com", transport=MyTransport())
Examples
See the examples/ directory:
balance.py— Check account balanceorder_number.py— Order a phone numberfull_workflow.py— Complete SMS verification workflow
Testing
pip install pytest
pytest
License
MIT — see LICENSE.
Links
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file virtualsmslabs_python_sdk-1.0.0.tar.gz.
File metadata
- Download URL: virtualsmslabs_python_sdk-1.0.0.tar.gz
- Upload date:
- Size: 13.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
23470835eeadd1ee6073c18fa0d7bcb76fc4f17cb9c7c903406e2195c4263139
|
|
| MD5 |
a3453239edb3c54c7a56d849f41caa6b
|
|
| BLAKE2b-256 |
b2df08bc346861b01cb40e64d922e11f1101c1be789298d518c17338a84fc32c
|
File details
Details for the file virtualsmslabs_python_sdk-1.0.0-py3-none-any.whl.
File metadata
- Download URL: virtualsmslabs_python_sdk-1.0.0-py3-none-any.whl
- Upload date:
- Size: 12.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
856d5cf5334d66443385c5211160bedfbbf47606e6d9804faf71d50d6bfeb567
|
|
| MD5 |
51af3505dbc49bc759a246f49ca08dd4
|
|
| BLAKE2b-256 |
b6d35adced1576c9945b9f26250eb12ee458b74d03dd9b1b8e4c7596b489d953
|