POST with a JSON body in a stable envelope. The envelope carries delivery and routing metadata; the data object carries the event itself.
The envelope
The envelope is shared by every event type; each event’sdata schema and example payloads live in the catalog below.
Fields
| Field | Type | Description |
|---|---|---|
schema_version | string | Payload schema version. See Payload versioning. |
event_id | string (UUID) | Unique identifier for this event - equals the Webhook-Id header, your idempotency key. |
event_type | string (open enum) | What happened, e.g. "transfer.received". |
subscription_id | string (UUID) | The subscription that matched and produced this delivery. Use it to route the event back to the address/chain you registered. |
occurred_at | string | null (ISO-8601) | When the event happened on-chain, or null when that time isn’t available. Always UTC, ends in Z, with exactly 3 fractional digits (milliseconds). |
data | object | The event payload. Its shape depends on event_type - see the event catalog. |
Example
Example delivery (transfer.received)
Payload versioning
schema_version is pinned per subscription: a subscription is pinned to the version current at creation and keeps receiving that version’s payloads for its lifetime.
- Within a version, evolution is additive. New fields may be added to the envelope or the
dataobject. Existing fields keep their names, types, and meaning. Your parser must tolerate unknown fields rather than reject them. - Breaking changes ship as a new version. If a field is ever renamed, removed, or has its type changed, that arrives as a new
schema_version. Existing subscriptions stay on their pinned version until you explicitly opt in.
Event catalog
One entry per event type: what fires it, thedata schema, and example payloads.
transfer.received
Fired once per incoming transfer to a watched address, when WalletSuite first observes it on-chain. Thedata object:
| Field | Type | Description |
|---|---|---|
chain | string (open enum) | The chain the transfer happened on, e.g. "ethereum", "tron". |
direction | string | Transfer direction relative to the watched address, e.g. "incoming". |
tx_hash | string | The transaction hash on the source chain. |
block_number | number | Block height in which the transfer was included. |
from | string | Sender address, in the chain’s canonical encoding - see Address encodings. |
to | string | Recipient address - the watched address that matched your subscription. Same encoding as from. |
amount | string | Transfer amount in token units, as a decimal string - see the warning below. |
asset_type | string (open enum) | The asset standard of the transfer, e.g. "native", "erc20", "trc20". Branch on this field to decide how to interpret the asset - never infer from asset_contract nullability. |
asset_contract | string | null | The token contract address, in the chain’s canonical encoding. null for native transfers, and may also be null for a token transfer when the contract address isn’t available. |
Example payloads
Four completetransfer.received payloads - one per asset shape.
- Ethereum - native ETH
- Ethereum - ERC-20 (USDC)
- Tron - native TRX
- Tron - TRC-20 (USDT)
ETH native transfer
Address encodings
from, to, and asset_contract use each chain’s canonical address encoding, consistent with the rest of the WalletSuite API. On input - for example, when you register a subscription - common representations of an address are accepted and normalized to that canonical form.
Event kinds vs event types
Two different concepts share similar names:| Concept | Where it lives | What it is |
|---|---|---|
eventKinds | On the subscription (you set it when you POST /api/notifications/subscriptions) | Asset-scope filters that decide which transfers you get notified about. Values: "INCOMING_NATIVE", "INCOMING_FUNGIBLE". |
event_type | On the delivered payload (the envelope) | The type of event that actually arrived on the wire, e.g. "transfer.received". |
eventKinds is a subscribe-time filter, not a delivered field. Subscribing with ["INCOMING_NATIVE"] means you only receive native-coin transfers; ["INCOMING_FUNGIBLE"] means only token transfers; both means both. Either way, you distinguish native from token deliveries by reading asset_type on the payload, not by inspecting eventKinds (which is never sent). See Quickstart for creating subscriptions.
Related
Quickstart
Create a subscription, provision a signing secret, and receive your first event.
Verify Signatures
Validate the Standard Webhooks signature against the raw request body.
Delivery & Retries
Acknowledgement window, retry schedule, ordering, and at-least-once semantics.
Troubleshooting
When a payload fails to verify or never arrives - resolution checklists and FAQ.
Best Practices
Idempotency, async processing, and hardening your endpoint for production.