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.
| Webhook | Telegram | |
|---|---|---|
| Delivery | HTTP POST to your endpoint | Bot message to a chat |
| Format | JSON (TransactionAlertPayload) | Formatted text message |
| Best for | Automated systems, backends | Human monitoring, alerts |
| Setup | URL + optional custom headers | Bot token + chat_id |
Webhook channels send an HTTP POST request with a JSON payload to your endpoint each time a tracked transaction is detected.
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"
}
}
}'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-Idheader. 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 -
truewhen the payload was triggered by the test action,falsefor real blockchain events.
Every webhook request includes four headers:
| Header | Description |
|---|---|
X-Webhook-Signature | Stripe-format HMAC-SHA256 signature: t=<unix-seconds>,v1=<hex> — timestamp is inside this header as t= |
X-Webhook-Event | Event 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-Id | UUIDv5 — stable across retries, use for deduplication |
X-Webhook-Delivery-Id | UUID — changes on every attempt, use for support correlation only |
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 send formatted messages to a Telegram chat via the Bot API.
- Create a bot with @BotFather and save the bot token.
- Add the bot to your target chat (group, channel, or direct message).
- Get the chat ID (use @userinfobot or the Telegram
getUpdatesAPI).
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:
| Field | Type | Description |
|---|---|---|
bot_token | string | Token from @BotFather ({bot_id}:{auth_token}) |
chat_id | integer | Target chat ID (positive for DMs, negative for groups/channels) |
language | string | Message language ("en", "ru", etc.) |
thread_id | integer | Forum topic thread ID (0 for no specific thread) |
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:
| Parameter | Type | Description |
|---|---|---|
is_success | boolean | Filter by outcome. true for successful deliveries (HTTP 2xx), false for failures. Omit to return all. |
event_type | string | Filter by subscription event type: transaction_detected or transaction_confirmed. |
page | integer | Page number for pagination. |
limit | integer | Number 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=falseto find the HTTP status codes and error details returned by your endpoint. - Use the
is_testfield on each log entry to separate test traffic from production deliveries.
Channels follow a fixed lifecycle: create, test, use, update, delete.
| Action | Endpoint | Description |
|---|---|---|
| Create | POST /channels | Create a new channel |
| Test | POST /channels/{channel_id}/actions/test | Send a test payload to verify delivery |
| Update | PATCH /channels/{channel_id} | Update channel name or config |
| Delete | DELETE /channels/{channel_id} | Permanently remove the 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.
- Test before relying on a channel. Send a test payload immediately after creation.
- Verify webhook signatures. Always validate
X-Webhook-Signatureto ensure payloads are authentic. See Authentication for code examples. - Handle duplicates. Use
X-Webhook-Event-Id(or theevent_idbody 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).