Every webhook delivery from Off the Hook is a Standard Webhooks-compliant HTTP POST to your destination URL. The body is a JSON envelope with a consistent shape across all event types: a unique event ID, a kind string that identifies what happened, a timestamp, and aDocumentation Index
Fetch the complete documentation index at: https://docs.offthehook.dev/llms.txt
Use this file to discover all available pages before exploring further.
data object containing the chain-specific transfer details. Your endpoint can use these fields to identify the event, verify it hasn’t been processed before, and extract the transfer information you need.
Payload structure
Envelope fields
Unique event identifier, prefixed
evt_. This ID is stable across retries — if Off the Hook retries a failed delivery, the same id appears in every attempt. Use it as your idempotency key to avoid processing the same transfer twice.The event type string, such as
"wallet.transfer.broadcasted". Your subscription only receives events whose kinds appear in its events array. See event types for all supported values.ISO 8601 timestamp of when the event was generated.
Transfer data fields
CAIP-2 chain identifier for the network where the transfer occurred, such as
"tron:mainnet". See supported networks.The block number that included this transfer.
The hash of the block that included this transfer.
Unix timestamp of the block in milliseconds.
The TRON transaction ID.
Position of this transfer within the block. For TRC-20 tokens this is the index of the
Transfer log event (0-based). For native TRX transfers this is always -1 — a deliberate sentinel that avoids colliding with the first TRC-20 log in the same transaction.Sender address in canonical TRON base58check format (starts with
T).Recipient address in canonical TRON base58check format.
Raw integer transfer amount as a string. Divide by
10^asset.decimals to get the human-readable value. For example, "1500000000" with decimals: 6 is 1,500 USDT.Describes the transferred token.
The addresses from your subscription’s filter list that caused this event to fire. Each entry includes the chain, the address, and the
role it played in the transfer: "from" if the address sent the funds, or "to" if it received them. A single transfer can match the same address in both roles if your filter includes both sender and recipient.Deduplication
Off the Hook retries deliveries on5xx, 408, 429, and network errors using a backoff schedule of 200ms, 1s, 5s, 1min, 5min, 30min, and 2h. Every attempt — original and retries — carries the same webhook-id header, which matches the id field in the payload body.
To avoid processing the same transfer twice, record the webhook-id of every delivery you successfully handle and skip any delivery whose ID you’ve already seen.
Delivery headers
Each POST request Off the Hook sends includes the following headers:| Header | Value |
|---|---|
content-type | application/json |
webhook-id | Event ID (e.g. evt_8xN9kP2QbA...) |
webhook-timestamp | Unix timestamp (seconds) |
webhook-signature | v1,<base64-hmac-sha256> |
x-oth-subscription-id | Your subscription ID |
user-agent | OffTheHook/0.1 |
webhook-signature header contains multiple v1, values separated by spaces — one for each active secret. A valid signature from any of them means the delivery is authentic.
Next steps
- Event types — full catalog of supported event kinds
- Verifying signatures — how to validate the HMAC signature on each delivery