Docs / Quickstart

Quickstart

From signup to your first confirmed-deposit webhook in about 5 minutes.

1. Create an account and an API key

  1. Sign up at tronhooks.com/app (email + password).
  2. In API keys, create a key. Prefixes are network-bound: tw_test_… works against Nile testnet deployments, tw_live_… against mainnet (this instance). The key is shown once — store it now.

2. Watch an address

curl -X POST https://tronhooks.com/v1/watches \
  -H "Authorization: Bearer tw_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "address": "TYourAddress...",
    "asset_filter": "USDT",
    "webhook_url": "https://your-server.example/tron-hook"
  }'

The 201 response contains the watch and — exactly once — its signing secret (whsec_…). Store it next to the endpoint that will receive the webhooks.

⚠️ The secret is shown only once. It is stored encrypted on our side and can never be retrieved again — if you lose it, delete the watch and create a new one.

Activation: a new watch becomes effective within ~3 seconds (one scan cycle). Transfers that happened before activation are never matched retroactively.

Or with the TypeScript SDK (npm i @tronhooks/sdk):

import { TronHooks } from '@tronhooks/sdk';

const th = new TronHooks('tw_live_...');
const watch = await th.watches.create({
  address: 'TYourAddress...',
  assetFilter: 'USDT',          // USDT | TRX | ALL
  webhookUrl: 'https://your-server.example/tron-hook',
});
// store watch.secret

3. Receive and verify the webhook

When a deposit is confirmed (solidity-node finality), we POST a JSON payload with an X-Signature header. Verify it against the raw request body:

import express from 'express';
import { constructEvent } from '@tronhooks/sdk';

const app = express();
app.post('/tron-hook', express.raw({ type: 'application/json' }), (req, res) => {
  const event = constructEvent(req.body, req.header('x-signature'), process.env.WHSEC);
  console.log(`${event.amount} ${event.asset} → ${event.to} (tx ${event.tx_id})`);
  res.sendStatus(200); // any 2xx acknowledges delivery
});

You MUST verify against the raw request body — the exact bytes received, before any JSON parsing. Any re-serialization (JSON.stringify(req.body), framework body parsers, pretty-printing) changes byte order and will make verification fail. That's why the example uses express.raw(). Details and Python/no-SDK variants: Verifying webhooks.

4. Reconcile any time

curl https://tronhooks.com/v1/events?limit=10 \
  -H "Authorization: Bearer tw_live_..."

GET /v1/events returns every event with its delivery status — your safety net if your receiver was down. Deliveries are at-least-once: dedupe on event_id.

No code? Telegram path

  1. Sign up at /app.
  2. Click Connect Telegram → open the link → press Start (works for groups too: add @tronhooks_bot and send /bind <code>).
  3. Add an address with the → Telegram target. Done — confirmed deposits arrive as Telegram messages with a Tronscan link.

Troubleshooting: no webhook arriving?

  1. Your URL is unreachable — or rejected by our SSRF rules. The endpoint must be a publicly resolvable http(s) URL; private/reserved addresses (localhost, 10.x, 192.168.x, cloud-metadata IPs…) are refused at creation and at delivery time. Tunnels (or our webhook debugger) help during development.
  2. Signature verification fails on your side. Almost always the raw-body rule above — a body parser touched the bytes before your HMAC. Fix the middleware order, don't disable verification.
  3. Check the delivery log. Console → Events & delivery log → click the event: every attempt's HTTP status and error is recorded (retries run 1m/5m/30m/2h/6h, then dead-letter). GET /v1/events shows the same via API.

Error responses you might hit along the way: error code table.

That's the whole integration. Free tier: 3 watched addresses, no card required.

Open the console