integrations
Send crypto address alerts to n8n
TxMeter watches public Ethereum, Polygon, Arbitrum and Tron addresses and posts every alert - money in, money out, a new counterparty, a token approval, a low balance, a silent address - as a signed JSON POST. n8n's own Webhook node receives it, so there is no community node to install: the workflow below runs on n8n Cloud and on a self-hosted n8n alike.
01
Import the workflow
In n8n open a new workflow, then ⋯ → Import from File and pick txmeter-n8n-alerts.json. Eight nodes: receive, read the signature, compute it, compare, answer TxMeter, skip test pings, post to Telegram.
02
Give TxMeter the URL
Publish the workflow, open the TxMeter webhook node and copy its Production URL. Add it on the Webhooks page. It has to be public HTTPS: TxMeter refuses addresses on private networks, so a self-hosted n8n needs a public hostname.
03
Paste the signing secret
Under the new webhook, open Signing secret and paste it into the Secret field of the Compute signature node, in place of PASTE_YOUR_SIGNING_SECRET.
04
Connect Telegram and test
In Send to Telegram pick your bot credential and replace PASTE_YOUR_CHAT_ID. Press Send test on the Webhooks page: HTTP 200 means the signature matched, HTTP 401 means the secret is wrong.
signature check
Anyone who learns the URL can post to it, so the workflow only acts on requests TxMeter signed. The header is X-TxMeter-Signature: t=<unix>,v1=<hex>, where hex is HMAC-SHA256 of "<t>.<raw body>" with your signing secret. Three details the template already handles:
- The Webhook node has Raw Body on. The HMAC covers the exact bytes we sent; JSON that n8n parsed and printed again is not the same string.
- The HMAC runs in n8n's Crypto node, not in a Code node: n8n blocks require('crypto') in Code nodes unless the instance allows it.
- A delivery whose t is more than five minutes off is refused, so a captured request cannot be replayed later.
beyond telegram
Swap the last node for Slack, Discord, email, a Google Sheet or an HTTP call to your own system. The alert is in $json.payload, for example {{ $json.payload.data.alert.title }} or {{ $json.payload.data.event.explorer_url }}. Branch on data.alert.kind to route approvals to one channel and incoming payments to another. Retries reuse the same id, so drop one you have already handled.
{
"id": "alert_1042",
"type": "alert.created",
"created_at": "2026-10-05T09:12:44Z",
"data": {
"alert": {
"id": 1042,
"kind": "approval_granted",
"severity": "critical",
"title": "Unlimited USDT approval",
"body": "…",
"detected_at": "2026-10-05T09:12:44Z",
"context": {}
},
"address": {
"id": 7,
"chain": "ethereum",
"address": "0x…",
"label": "Treasury",
"explorer_url": "https://etherscan.io/address/0x…"
},
"event": {
"kind": "approval",
"tx_hash": "0x…",
"direction": "out",
"counterparty": "0x…",
"amount": "115792089237316195423570985008687907853269984665640564039457584007913129.639935",
"symbol": "USDT",
"token_address": "0x…",
"block_number": 21000000,
"occurred_at": "2026-10-05T09:11:59Z",
"explorer_url": "https://etherscan.io/tx/0x…"
}
}
}