Skip to main content

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.http logger).
  • 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 with await
  • SyncHeroSMSClient (sync) — same method names without await

Activation namespace parity (client.activations.*):

  • create(...)
  • attach(...)
  • list_active(...)
  • get_active_activations(...) (alias of list_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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

herosms-0.1.1.tar.gz (75.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

herosms-0.1.1-py3-none-any.whl (22.7 kB view details)

Uploaded Python 3

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

Hashes for herosms-0.1.1.tar.gz
Algorithm Hash digest
SHA256 1afb59b46da3b462cf3dd76f6197c6b81d456fea176358c95cd0c4d6c520ad0f
MD5 a714af8af61d75e743f78f0ceca137ce
BLAKE2b-256 0a688b61c07e0f78bc97c8e0aee8b3abf40943d5014c6179e4497131898b2558

See more details on using hashes here.

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

Hashes for herosms-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1ed8392ec930d5867a1a0a54abb6e18ff488f603cbad5d7791debe6dc6aa368b
MD5 b67d6f82aed19737ed14ed1a1ca5a1f6
BLAKE2b-256 487e453847dc50f08d1f9aaa13ddbb185b865a86010753a16528502767e90172

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page