Skip to content
Last updated

Notification channels

Notification channels are the delivery mechanism for blockchain event alerts. When Vilna detects activity on your monitored addresses, it sends a notification through your configured channels.

Two channel types are available: Webhook and Telegram.

Channel types at a glance

WebhookTelegram
DeliveryHTTP POST to your endpointBot message to a chat
FormatJSON (TransactionAlertPayload)Formatted text message
Best forAutomated systems, backendsHuman monitoring, alerts
SetupURL + optional custom headersBot token + chat_id

Blockchain webhook notifications

Webhook channels send an HTTP POST request with a JSON payload to your endpoint each time a tracked transaction is detected.

Creating a webhook channel

curl -X POST "https://api.vilna.io/v1/channels" \
  -H "X-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production Webhook",
    "config": {
      "kind": "webhook",
      "url": "https://api.example.com/webhooks/vilna",
      "headers": {
        "Authorization": "Bearer your-secret-token"
      }
    }
  }'

Webhook payload structure

Every webhook delivery sends a TransactionAlertPayload with four top-level fields:

{
  "event_id": "f47ac10b-58cc-5372-a567-0e02b2c3d479",
  "item": { /* Transaction object */ },
  "references": {
    "tokens": { /* token GID -> token details */ },
    "blockchains": { /* chain GID -> blockchain details */ },
    "addresses": { /* address -> label */ }
  },
  "is_test_message": false
}
  • event_id - UUIDv5 that matches the X-Webhook-Event-Id header. It is stable across retries and is part of the signed body, making it tamper-evident. Use it for deduplication.
  • item - the full transaction object including events (transfers, fees) and activity records with per-address deltas.
  • references - lookup maps for tokens, blockchains, and addresses referenced in the transaction, so you do not need additional API calls to resolve names and symbols.
  • is_test_message - true when the payload was triggered by the test action, false for real blockchain events.

Webhook security headers

Every webhook request includes four headers:

HeaderDescription
X-Webhook-SignatureStripe-format HMAC-SHA256 signature: t=<unix-seconds>,v1=<hex> — timestamp is inside this header as t=
X-Webhook-EventEvent name in dot notation: transaction.detected or transaction.confirmed. Test deliveries reuse the same value — check is_test_message in the body to distinguish them.
X-Webhook-Event-IdUUIDv5 — stable across retries, use for deduplication
X-Webhook-Delivery-IdUUID — changes on every attempt, use for support correlation only

Verifying the signature

The webhook_secret field of the channel creation response is your signing key — store it immediately in a secrets manager, since it is not returned again outside of rotation. For verification code, deduplication patterns, the secret lifecycle endpoints, and the full list of required client behaviors, see Webhook signature verification.

Telegram channels

Telegram channels send formatted messages to a Telegram chat via the Bot API.

Setup

  1. Create a bot with @BotFather and save the bot token.
  2. Add the bot to your target chat (group, channel, or direct message).
  3. Get the chat ID (use @userinfobot or the Telegram getUpdates API).

Creating a Telegram channel

curl -X POST "https://api.vilna.io/v1/channels" \
  -H "X-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ops Alerts",
    "config": {
      "kind": "telegram",
      "bot_token": "123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789",
      "chat_id": -1001234567890,
      "language": "en",
      "thread_id": 0
    }
  }'

Config fields:

FieldTypeDescription
bot_tokenstringToken from @BotFather ({bot_id}:{auth_token})
chat_idintegerTarget chat ID (positive for DMs, negative for groups/channels)
languagestringMessage language ("en", "ru", etc.)
thread_idintegerForum topic thread ID (0 for no specific thread)

Delivery logs

Delivery logs record the outcome of every notification attempt for a channel - both webhook HTTP calls and Telegram bot messages. Use them to verify that notifications are reaching their destination and to debug failed deliveries.

Fetch logs with GET /channels/{channel_id}/logs. The response is a paginated list sorted by most recent delivery first.

Query parameters:

ParameterTypeDescription
is_successbooleanFilter by outcome. true for successful deliveries (HTTP 2xx), false for failures. Omit to return all.
event_typestringFilter by subscription event type: transaction_detected or transaction_confirmed.
pageintegerPage number for pagination.
limitintegerNumber of items per page.

Each log entry also has an is_test boolean — true for deliveries triggered by the test action, false for production events.

# List failed deliveries for a channel
curl "https://api.vilna.io/v1/channels/{channel_id}/logs?is_success=false" \
  -H "X-Api-Key: your-api-key"

When to use delivery logs:

  • After creating and testing a channel, confirm the test delivery was logged as successful.
  • When notifications stop arriving, query with is_success=false to find the HTTP status codes and error details returned by your endpoint.
  • Use the is_test field on each log entry to separate test traffic from production deliveries.

Channel lifecycle

Channels follow a fixed lifecycle: create, test, use, update, delete.

ActionEndpointDescription
CreatePOST /channelsCreate a new channel
TestPOST /channels/{channel_id}/actions/testSend a test payload to verify delivery
UpdatePATCH /channels/{channel_id}Update channel name or config
DeleteDELETE /channels/{channel_id}Permanently remove the channel

Testing a channel

Always test a channel after creation to verify delivery works:

curl -X POST "https://api.vilna.io/v1/channels/{channel_id}/actions/test" \
  -H "X-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{ "event_type": "transaction_detected" }'

The test sends a sample TransactionAlertPayload with is_test_message: true.

Best practices

  • Test before relying on a channel. Send a test payload immediately after creation.
  • Verify webhook signatures. Always validate X-Webhook-Signature to ensure payloads are authentic. See Authentication for code examples.
  • Handle duplicates. Use X-Webhook-Event-Id (or the event_id body field) to skip duplicate deliveries — it is stable across retries.
  • Respond quickly. Webhook endpoints must return HTTP 2xx within 10 seconds. Process the payload asynchronously.
  • Use separate channels for different environments (development, staging, production) and different purposes (critical alerts vs routine notifications).

Further reading