Async Python client for HeroSMS (sms-activate.ru compatible) API
Project description
herosms
Async and sync Python client for HeroSMS (SMS-Activate compatible API).
Features
- Async-first client with context-manager support
- Synchronous wrapper for non-async projects
- Activation lifecycle helpers (create, wait, resend, complete, cancel)
- Rent APIs support
- Reference data helpers (countries, services, operators, prices)
- Typed models with Pydantic v2
- Custom exception hierarchy
- Webhook payload parsing for incoming SMS events
Installation
pip install herosms
For development:
uv sync --extra dev
Quickstart (async)
import asyncio
from herosms import HeroSMSClient
async def main() -> None:
async with HeroSMSClient(api_key="YOUR_API_KEY") as client:
balance = await client.get_balance()
print(f"Balance: {balance}")
activation = await client.activations.create(service="tg", country=6)
print("Phone:", activation.phone) # available immediately
status = await activation.wait_for_sms(timeout=120)
print("Code:", status.code)
await activation.complete()
asyncio.run(main())
Quickstart (sync)
from herosms import SyncHeroSMSClient
with SyncHeroSMSClient(api_key="YOUR_API_KEY") as client:
balance = client.get_balance()
print(f"Balance: {balance}")
Response formats (response_format)
Most methods support response_format with three modes:
"model"(default): return typed Pydantic models / parsed structures."json": return transport payload as JSON-compatible value."raw": return raw API payload as plain string.
For endpoints that return legacy plain text (for example ACCESS_BALANCE:0.84 or STATUS_WAIT_CODE), response_format="json" wraps text into:
{"type": "text", "raw": "..."}
This keeps JSON mode consistent even when the upstream API responds with plain text.
HTTP debug logging
Enable HTTP debug logs when constructing the client:
from herosms import HeroSMSClient
client = HeroSMSClient(
api_key="YOUR_API_KEY",
debug=True,
log_body_max_length=500,
)
Parameters:
debug: enables request/response debug logs (herosms.httplogger).log_body_max_length: maximum number of response-body characters to log.log_body_max_length=None: disables trimming and logs full body.
Activation lifecycle
Manual mode (recommended, immediate phone)
activation = await client.activations.create(service="tg", country=6)
print(activation.phone) # available right after create
status = await activation.wait_for_sms(timeout=120)
print(status.code)
await activation.complete()
# or
await activation.cancel()
Async context manager mode (async with)
async with await client.activations.create(service="tg", country=6) as activation:
status = await activation.wait_for_sms(timeout=120)
print(status.code)
await activation.complete()
Continue existing activation by activation_id (attach)
activation = client.activations.attach(
activation_id=777001,
phone_number="79990009999", # optional
)
status = await activation.wait_for_sms(timeout=120)
print(status.code)
await activation.complete()
Request another SMS:
await activation.request_sms()
Get all OTP messages for activation:
messages = await activation.get_all_sms()
Legacy status endpoint (getStatus)
Use get_status_v1 if you need raw text-compatible status values from legacy integrations:
raw_status = await client.get_status_v1(activation_id=123456)
print(raw_status) # e.g. STATUS_WAIT_CODE or STATUS_OK:1234
Sync variant:
raw_status = client.get_status_v1(activation_id=123456)
Sync/async parity
Both clients expose the same core API surface:
HeroSMSClient(async) — use withawaitSyncHeroSMSClient(sync) — same method names withoutawait
Activation namespace parity (client.activations.*):
create(...)attach(...)list_active(...)get_active_activations(...)(alias oflist_active)get_history(...)finish(...)cancel(...)get_sms(...)
get_active_activations examples
Async:
active = await client.activations.get_active_activations(limit=10)
print(active)
Sync:
active = client.activations.get_active_activations(limit=10)
print(active)
History examples
Async:
history = await client.get_history(size=20)
print(history)
Sync:
history = client.get_history(size=20)
print(history)
Rent flow
Check availability:
Async:
availability = await client.get_rent_availability(service="tg", country=6)
print(availability)
Sync:
availability = client.get_rent_availability(service="tg", country=6)
print(availability)
Rent a number:
Async:
rent_activation = await client.rent_number(service="tg", country=6, duration=2)
print(rent_activation.phone)
Sync:
rent_activation = client.rent_number(service="tg", country=6, duration=2)
print(rent_activation.phone)
Reference data APIs
countries = await client.get_countries()
services = await client.get_services(country=6)
operators = await client.get_operators(country=6)
prices = await client.get_prices(service="tg", country=6)
top = await client.get_top_countries(service="tg", by_rank=True)
Error handling
All library exceptions inherit from HeroSMSError.
from herosms import HeroSMSError
try:
...
except HeroSMSError as exc:
print(f"HeroSMS error: {exc}")
Webhook payload parsing (smsIncoming)
Parse and validate incoming webhook payload with Pydantic model:
from herosms import WebhookSMSIncoming
payload = {
"activationId": "635468024",
"service": "tg",
"text": "Telegram code 123456",
"code": "123456",
"country": 6,
"receivedAt": "2026-02-16T12:36:59+03:00",
}
event = WebhookSMSIncoming.model_validate(payload)
print(event.activation_id, event.code)
API compatibility note
HeroSMS is compatible with SMS-Activate-style API actions. This library targets HeroSMS endpoints while preserving familiar SMS-Activate action semantics.
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 herosms-0.1.1.tar.gz.
File metadata
- Download URL: herosms-0.1.1.tar.gz
- Upload date:
- Size: 75.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1afb59b46da3b462cf3dd76f6197c6b81d456fea176358c95cd0c4d6c520ad0f
|
|
| MD5 |
a714af8af61d75e743f78f0ceca137ce
|
|
| BLAKE2b-256 |
0a688b61c07e0f78bc97c8e0aee8b3abf40943d5014c6179e4497131898b2558
|
File details
Details for the file herosms-0.1.1-py3-none-any.whl.
File metadata
- Download URL: herosms-0.1.1-py3-none-any.whl
- Upload date:
- Size: 22.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1ed8392ec930d5867a1a0a54abb6e18ff488f603cbad5d7791debe6dc6aa368b
|
|
| MD5 |
b67d6f82aed19737ed14ed1a1ca5a1f6
|
|
| BLAKE2b-256 |
487e453847dc50f08d1f9aaa13ddbb185b865a86010753a16528502767e90172
|