Skip to main content
Webhooks deliver real-time POST notifications to your server when blockchain events occur. The SDK provides a low-level client for webhook CRUD and a high-level dispatcher with decorator-based event handling.
API key is required for all webhook operations. Get one at tonconsole.com.

Architecture

ComponentDescription
TonapiWebhookClientHTTP client for webhook CRUD — create, list, delete, subscribe/unsubscribe.
TonapiWebhookBound webhook object — manages subscriptions without explicit ID.
TonapiWebhookDispatcherDecorator-based event dispatcher — register handlers, auto-setup, process incoming events.

Event Types

TypeEnumDecoratorDescription
Account TXACCOUNT_TX@dispatcher.account_tx()Account transactions.
Mempool MSGMEMPOOL_MSG@dispatcher.mempool_msg()Pending mempool messages.
Opcode MSGOPCODE_MSG@dispatcher.opcode_msg()Messages filtered by opcode.
New ContractsNEW_CONTRACTS@dispatcher.new_contracts()New contract deployments.

Endpoints

NetworkURL
Mainnethttps://rt.tonapi.io
Testnethttps://rt-testnet.tonapi.io

Quick Example

FastAPI integration with automatic webhook setup and event dispatch:
from contextlib import asynccontextmanager

import uvicorn
from fastapi import FastAPI, Request, Response

from pytonapi.types import Network
from pytonapi.webhook import (
    AccountTxEvent,
    TonapiWebhookClient,
    TonapiWebhookDispatcher,
)

client = TonapiWebhookClient("YOUR_API_KEY", Network.MAINNET)
dispatcher = TonapiWebhookDispatcher(
    "https://example.com/webhook",
    client=client,
    accounts=["EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2"],
)


@dispatcher.account_tx()
async def on_tx(event: AccountTxEvent) -> None:
    print(f"TX: {event.tx_hash}")


async def handle_webhook(request: Request) -> Response:
    await dispatcher.process(
        request.url.path,
        await request.json(),
        authorization=request.headers.get("Authorization"),
    )
    return Response(status_code=200)


@asynccontextmanager
async def lifespan(application: FastAPI):
    await dispatcher.setup()
    for path in dispatcher.paths.values():
        application.add_api_route(path, handle_webhook, methods=["POST"])
    yield
    await dispatcher.teardown()


app = FastAPI(lifespan=lifespan)

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)
See Guide for the full client API, dispatcher options, and aiohttp integration.
Each webhook has a unique secret token. TON API sends it as Authorization: Bearer {token} with every event delivery — use it to verify that incoming requests are genuine. The dispatcher verifies it automatically in process().

Event Models

All models are Pydantic BaseModel subclasses.
from pytonapi.webhook import AccountTxEvent, MempoolMsgEvent, OpcodeMsgEvent, NewContractsEvent
FieldTypeDescription
event_typeLiteral["account_tx"]Always "account_tx".
account_idstrAccount address.
ltintLogical time.
tx_hashstrTransaction hash.
{
  "event_type": "account_tx",
  "account_id": "0:408da3b28b6c065a593e10391269baaa9c5f8caebc0c69d9f0aabbab2a99256b",
  "lt": 49739623000001,
  "tx_hash": "653e593d581ad40d5d0868fe5d60008e1bfe9d2d4c4fa6b2ee5cd458741d7b59"
}
FieldTypeDescription
event_typeLiteral["mempool_msg"]Always "mempool_msg".
bocstrBase64-encoded BOC.
{
  "event_type": "mempool_msg",
  "boc": "te6cckEBAQEADgAAGEhlbGxvIFRPTiEN"
}
FieldTypeDescription
event_typeLiteral["opcode_msg"]Always "opcode_msg".
account_idstrAccount address.
ltintLogical time.
tx_hashstrTransaction hash.
{
  "event_type": "opcode_msg",
  "account_id": "0:408da3b28b6c065a593e10391269baaa9c5f8caebc0c69d9f0aabbab2a99256b",
  "lt": 49739623000001,
  "tx_hash": "653e593d581ad40d5d0868fe5d60008e1bfe9d2d4c4fa6b2ee5cd458741d7b59"
}
FieldTypeDescription
event_typeLiteral["new_contracts"]Always "new_contracts".
account_idstrAccount address.
ltintLogical time.
tx_hashstrTransaction hash.
{
  "event_type": "new_contracts",
  "account_id": "0:408da3b28b6c065a593e10391269baaa9c5f8caebc0c69d9f0aabbab2a99256b",
  "lt": 49739623000001,
  "tx_hash": "653e593d581ad40d5d0868fe5d60008e1bfe9d2d4c4fa6b2ee5cd458741d7b59"
}
All webhook events are finalized — there is no pending/confirmed distinction unlike streaming mempool events.