Metadata-Version: 2.4
Name: numberotp
Version: 0.1.0
Summary: Official NumberOTP API client — virtual numbers for SMS / OTP verification
Project-URL: Homepage, https://www.numberotp.com/developers/sdks
Project-URL: Documentation, https://www.numberotp.com/docs/sdks
Project-URL: API reference, https://www.numberotp.com/docs/api
Project-URL: Source, https://github.com/DishantSinghDev2/numberotp-python
Author-email: NumberOTP <support@numberotp.com>
License-Expression: MIT
License-File: LICENSE
Keywords: numberotp,otp,phone verification,sms,virtual number
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: AsyncIO
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx<1,>=0.27
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# numberotp (Python)

The official Python client for the [NumberOTP API](https://www.numberotp.com/docs/api): real phone numbers for SMS / OTP verification. It has sync and async clients, is fully typed, and supports Python 3.9+.

```bash
pip install numberotp
```

Get an API key at [numberotp.com/dashboard/developer](https://www.numberotp.com/dashboard/developer) and set it as `NOTP_API_KEY`. Guides: [numberotp.com/docs/sdks](https://www.numberotp.com/docs/sdks).

```python
from numberotp import NumberOTP

client = NumberOTP()  # reads NOTP_API_KEY

act = client.activations.create_and_wait(
    service="wa", country="16",
    on_number=lambda n: print("Use this number:", n["phoneNumber"]),
)
print("Code:", act["otp"])
```

### Async
```python
from numberotp import AsyncNumberOTP

async with AsyncNumberOTP() as client:
    n = await client.activations.create(service="tg", country="187")
    act = await client.activations.wait_for_code(n["data"]["id"], timeout=600)
```

### More
```python
client.services.search(q="discord.com")
client.prices.get(service="wa")
client.activations.resend(id) / finish(id) / cancel(id)   # cancel → full refund
for event in client.events.stream():                      # live events, reconnects by itself
    ...
from numberotp import verify_webhook                      # check x-numberotp-signature
client.auth.device_login(lambda c: print(c["user_code"]))  # sign a user in (CLI-style)
```

### Errors and reliability
- Errors carry `.status` and a stable `.code`: `InsufficientBalanceError`, `NotFoundError`, `ConflictError`, `ActivationClosedError`, `WaitTimeoutError` and others.
- Purchases send an `Idempotency-Key`, so retries never buy twice.
- Expired access tokens refresh automatically.
