virtualsmslabs-python-sdk 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ *.egg
6
+ dist/
7
+ build/
8
+ .eggs/
9
+ .pytest_cache/
10
+ .coverage
11
+ htmlcov/
12
+ .tox/
13
+ *.log
14
+ .venv/
15
+ venv/
16
+ env/
17
+ .idea/
18
+ .vscode/
19
+ *.swp
20
+ *.swo
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 VirtualSMS Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,352 @@
1
+ Metadata-Version: 2.4
2
+ Name: virtualsmslabs-python-sdk
3
+ Version: 1.0.0
4
+ Summary: Python SDK for the VirtualSMS Consumer API — SMS verification, phone number rental, and activation management.
5
+ Project-URL: Homepage, https://virtualsms.de
6
+ Project-URL: Documentation, https://virtualsms.de/docs/sdk
7
+ Project-URL: Repository, https://github.com/VirtualSMSLabs/python-sdk
8
+ Project-URL: Issues, https://github.com/VirtualSMSLabs/python-sdk/issues
9
+ Author-email: VirtualSMS Labs <contact@virtualsms.de>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: otp,phone,sms,sms-activate,verification,virtual,virtualsms
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Communications :: Telephony
24
+ Requires-Python: >=3.9
25
+ Description-Content-Type: text/markdown
26
+
27
+ # VirtualSMS Python SDK
28
+
29
+ Python SDK for the VirtualSMS Consumer API — SMS verification, phone number rental, and activation management.
30
+
31
+ [![PyPI](https://img.shields.io/pypi/v/virtualsmslabs-python-sdk)](https://pypi.org/project/virtualsmslabs-python-sdk/)
32
+ [![License](https://img.shields.io/github/license/VirtualSMSLabs/python-sdk)](LICENSE)
33
+ [![Python](https://img.shields.io/pypi/pyversions/virtualsms)](https://www.python.org/)
34
+
35
+ ## Requirements
36
+
37
+ - Python 3.9 or higher
38
+ - No external dependencies (uses standard library only)
39
+
40
+ ## Installation
41
+
42
+ ```bash
43
+ pip install virtualsmslabs-python-sdk
44
+ ```
45
+
46
+ ## Quick Start
47
+
48
+ ```python
49
+ from virtualsms import VirtualSMSClient, ActivationStatus
50
+
51
+ client = VirtualSMSClient("YOUR_API_KEY", "https://api.virtualsms.de")
52
+
53
+ # Check balance
54
+ balance = client.get_balance()
55
+ print(f"Balance: ${balance.balance:.2f}")
56
+
57
+ # Order a WhatsApp number in Brazil
58
+ number = client.get_number("wa", 73, max_price=2.00)
59
+ print(f"Number: {number.phone_number} (ID: {number.activation_id})")
60
+
61
+ # Set status to ready (SMS sent)
62
+ client.set_status(number.activation_id, ActivationStatus.READY)
63
+
64
+ # Poll for SMS code
65
+ status = client.get_status(number.activation_id)
66
+ if status.code is not None:
67
+ print(f"SMS code: {status.code}")
68
+ # Complete the activation
69
+ client.set_status(number.activation_id, ActivationStatus.COMPLETE)
70
+ ```
71
+
72
+ ## API Reference
73
+
74
+ ### Client Constructor
75
+
76
+ ```python
77
+ client = VirtualSMSClient(
78
+ api_key="YOUR_API_KEY", # Your API key (required)
79
+ base_url="https://api.virtualsms.de", # API base URL (optional)
80
+ transport=None, # Optional custom transport
81
+ )
82
+ ```
83
+
84
+ ### Methods
85
+
86
+ #### Account
87
+
88
+ ##### `get_balance() -> BalanceResponse`
89
+
90
+ Returns the current account balance.
91
+
92
+ ```python
93
+ balance = client.get_balance()
94
+ print(balance.balance) # 10.50
95
+ ```
96
+
97
+ #### Information & Pricing
98
+
99
+ ##### `get_countries(pool_provider=None) -> dict`
100
+
101
+ Returns all available countries.
102
+
103
+ ##### `get_services_list(country=None, lang=None) -> dict`
104
+
105
+ Returns available services for a country.
106
+
107
+ ##### `get_operators(country, pool_provider=None) -> list`
108
+
109
+ Returns available mobile operators for a country.
110
+
111
+ ##### `get_prices(service=None, country=None, pool_provider=None) -> dict`
112
+
113
+ Returns pricing data organized by country and service.
114
+
115
+ ##### `get_prices_extended(service=None, country=None, free_price=None, pool_provider=None) -> dict`
116
+
117
+ Returns extended pricing with price tiers.
118
+
119
+ ##### `get_prices_verification(service=None, pool_provider=None) -> dict`
120
+
121
+ Returns pricing in inverted format (service → country).
122
+
123
+ ##### `get_numbers_status(country, operator=None, pool_provider=None) -> dict`
124
+
125
+ Returns available phone quantity per service.
126
+
127
+ ##### `get_top_countries_by_service(service) -> list`
128
+
129
+ Returns top 10 countries for a service, ranked by purchase share and success rate.
130
+
131
+ #### Ordering Numbers
132
+
133
+ ##### `get_number(service, country, **options) -> NumberResponse`
134
+
135
+ Orders a phone number. Returns text format response.
136
+
137
+ ```python
138
+ number = client.get_number(
139
+ service="wa",
140
+ country=73,
141
+ max_price=2.00,
142
+ operator="claro",
143
+ forward=True,
144
+ )
145
+ print(number.activation_id) # 123
146
+ print(number.phone_number) # 447777777777
147
+ ```
148
+
149
+ **Options:**
150
+
151
+ | Parameter | Type | Description |
152
+ |-----------|------|-------------|
153
+ | `max_price` | `float` | Maximum price willing to pay |
154
+ | `operator` | `str` | Mobile operator filter |
155
+ | `phone_exception` | `str` | Phone prefixes to exclude (comma-separated) |
156
+ | `forward` | `bool` | Enable call forwarding |
157
+ | `activation_type` | `int` | Activation type: 0=SMS, 1=number, 2=voice |
158
+ | `language` | `str` | Language for voice activation |
159
+ | `use_cashback` | `bool` | Use cashback balance first |
160
+ | `user_id` | `str` | End-user ID for tracking |
161
+ | `ref` | `str` | Referral ID |
162
+ | `pool_provider` | `str` | Pool provider: alpha, prime, gamma, zeta |
163
+
164
+ ##### `get_number_v2(service, country, **options) -> dict`
165
+
166
+ Same as `get_number` but returns JSON with additional fields. Supports `order_id` for idempotency.
167
+
168
+ #### Activation Management
169
+
170
+ ##### `set_status(id, status) -> str`
171
+
172
+ Changes activation status.
173
+
174
+ ```python
175
+ from virtualsms import ActivationStatus
176
+
177
+ client.set_status(activation_id, ActivationStatus.READY) # 1 - SMS sent
178
+ client.set_status(activation_id, ActivationStatus.RETRY) # 3 - Request another SMS
179
+ client.set_status(activation_id, ActivationStatus.COMPLETE) # 6 - Finish
180
+ client.set_status(activation_id, ActivationStatus.CANCEL) # 8 - Cancel
181
+ ```
182
+
183
+ ##### `get_status(id) -> StatusResponse`
184
+
185
+ Returns activation status in text format.
186
+
187
+ ```python
188
+ status = client.get_status(activation_id)
189
+ print(status.status) # STATUS_OK, STATUS_WAIT_CODE, STATUS_CANCEL
190
+ print(status.code) # 123456 (None if not yet received)
191
+ ```
192
+
193
+ ##### `get_status_v2(id) -> dict`
194
+
195
+ Returns activation status in JSON format with SMS/call details.
196
+
197
+ ##### `get_active_activations() -> list`
198
+
199
+ Returns all currently active activations.
200
+
201
+ ##### `check_extra_activation(id) -> dict`
202
+
203
+ Checks if a number is available for reactivation.
204
+
205
+ ##### `get_extra_activation(id) -> NumberResponse`
206
+
207
+ Creates an extra activation on a previously used number.
208
+
209
+ #### Notifications
210
+
211
+ ##### `get_notifications() -> dict`
212
+
213
+ Returns user notifications including penalties, low balance alerts, and admin messages.
214
+
215
+ ### Constants
216
+
217
+ #### ActivationStatus
218
+
219
+ ```python
220
+ ActivationStatus.READY # 1 - SMS has been sent to the number
221
+ ActivationStatus.RETRY # 3 - Request another SMS code
222
+ ActivationStatus.COMPLETE # 6 - Finish activation
223
+ ActivationStatus.CANCEL # 8 - Cancel activation
224
+ ```
225
+
226
+ #### PoolProvider
227
+
228
+ ```python
229
+ PoolProvider.ALPHA # 'alpha'
230
+ PoolProvider.PRIME # 'prime'
231
+ PoolProvider.GAMMA # 'gamma'
232
+ PoolProvider.ZETA # 'zeta'
233
+ ```
234
+
235
+ ## Error Handling
236
+
237
+ The SDK raises typed exceptions for all API errors. Each error code maps to a specific exception class:
238
+
239
+ ```python
240
+ from virtualsms import (
241
+ VirtualSMSClient,
242
+ VirtualSMSException,
243
+ AuthenticationException,
244
+ InsufficientBalanceException,
245
+ NoNumbersException,
246
+ ValidationException,
247
+ ActivationException,
248
+ RateLimitException,
249
+ ServerException,
250
+ )
251
+
252
+ try:
253
+ number = client.get_number("wa", 73)
254
+ except AuthenticationException:
255
+ # BAD_KEY, BANNED, PURCHASE_RESTRICTED, SERVICE_RESTRICTED
256
+ pass
257
+ except InsufficientBalanceException:
258
+ # NO_BALANCE
259
+ pass
260
+ except NoNumbersException:
261
+ # NO_NUMBERS
262
+ pass
263
+ except ValidationException:
264
+ # WRONG_SERVICE, WRONG_COUNTRY, BAD_ACTION, BAD_STATUS, NO_PRICES, INVALID_PROVIDER
265
+ pass
266
+ except ActivationException:
267
+ # NO_ACTIVATION, WRONG_ACTIVATION_ID, EARLY_CANCEL_DENIED, RENEW_ACTIVATION_NOT_AVAILABLE
268
+ pass
269
+ except RateLimitException as e:
270
+ # CONCURRENT_LIMIT — check e.retry_after
271
+ pass
272
+ except ServerException:
273
+ # ERROR_SQL, unknown errors
274
+ pass
275
+ ```
276
+
277
+ ### Error Code Reference
278
+
279
+ | Error Code | Exception | Description |
280
+ |-----------|-----------|-------------|
281
+ | `BAD_KEY` | `AuthenticationException` | Invalid API key |
282
+ | `BANNED` | `AuthenticationException` | Account banned or IP blocked |
283
+ | `PURCHASE_RESTRICTED` | `AuthenticationException` | User restricted from purchasing |
284
+ | `SERVICE_RESTRICTED` | `AuthenticationException` | Service restricted for account |
285
+ | `NO_BALANCE` | `InsufficientBalanceException` | Insufficient balance |
286
+ | `NO_NUMBERS` | `NoNumbersException` | No numbers available |
287
+ | `WRONG_SERVICE` | `ValidationException` | Invalid service code |
288
+ | `WRONG_COUNTRY` | `ValidationException` | Invalid country ID |
289
+ | `BAD_ACTION` | `ValidationException` | Invalid action |
290
+ | `BAD_STATUS` | `ValidationException` | Invalid status code |
291
+ | `NO_PRICES` | `ValidationException` | No pricing data available |
292
+ | `INVALID_PROVIDER` | `ValidationException` | Invalid pool provider |
293
+ | `NO_ACTIVATION` | `ActivationException` | Activation not found |
294
+ | `WRONG_ACTIVATION_ID` | `ActivationException` | Invalid activation ID |
295
+ | `EARLY_CANCEL_DENIED` | `ActivationException` | Cannot cancel within 5 minutes |
296
+ | `RENEW_ACTIVATION_NOT_AVAILABLE` | `ActivationException` | Number not available for reactivation |
297
+ | `CONCURRENT_LIMIT` | `RateLimitException` | Too many concurrent activations |
298
+ | `ERROR_SQL` | `ServerException` | Internal server error |
299
+
300
+ ## Tracking Headers
301
+
302
+ The SDK sends anonymous tracking headers with every request for analytics and debugging:
303
+
304
+ | Header | Value | Privacy |
305
+ |--------|-------|---------|
306
+ | `X-SDK-Version` | `1.0.0` | SDK version string |
307
+ | `X-SDK-Language` | `python` | SDK language |
308
+ | `X-SDK-Machine-Id` | SHA-256 hash of `platform.platform()` + `sys.implementation.name` (truncated to 32 chars) | Irreversible hash — no hostname or IP exposed |
309
+ | `X-SDK-Timestamp` | ISO 8601 UTC timestamp | Request time |
310
+
311
+ No personally identifiable information is transmitted. The machine ID is a one-way hash and cannot be reversed to identify the source machine.
312
+
313
+ ## Custom Transport
314
+
315
+ By default, the SDK uses `urllib.request` for HTTP requests. You can provide your own transport implementation:
316
+
317
+ ```python
318
+ from virtualsms import VirtualSMSClient, Transport, Response
319
+
320
+ class MyTransport(Transport):
321
+ def send(self, url: str, headers: dict) -> Response:
322
+ # Your HTTP implementation
323
+ return Response(status_code=200, body="ACCESS_BALANCE:10.50")
324
+
325
+ client = VirtualSMSClient("API_KEY", "https://api.example.com", transport=MyTransport())
326
+ ```
327
+
328
+ ## Examples
329
+
330
+ See the `examples/` directory:
331
+
332
+ - [`balance.py`](examples/balance.py) — Check account balance
333
+ - [`order_number.py`](examples/order_number.py) — Order a phone number
334
+ - [`full_workflow.py`](examples/full_workflow.py) — Complete SMS verification workflow
335
+
336
+ ## Testing
337
+
338
+ ```bash
339
+ pip install pytest
340
+ pytest
341
+ ```
342
+
343
+ ## License
344
+
345
+ MIT — see [LICENSE](LICENSE).
346
+
347
+ ## Links
348
+
349
+ - [PyPI](https://pypi.org/project/virtualsmslabs-python-sdk/)
350
+ - [GitHub](https://github.com/VirtualSMSLabs/python-sdk)
351
+ - [API Documentation](https://virtualsms.de/docs)
352
+ - [MCP Integration](https://virtualsms.de/docs/mcp)