> ## Documentation Index
> Fetch the complete documentation index at: https://docs.walletsuite.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Events & Payloads

> The webhook envelope, the event catalog with schemas and example payloads, and the payload versioning contract.

Every WalletSuite webhook delivery is a single HTTP `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's `data` schema and example payloads live in the [catalog](#event-catalog) below.

### Fields

| Field             | Type                      | Description                                                                                                                                               |
| ----------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `schema_version`  | string                    | Payload schema version. See [Payload versioning](#payload-versioning).                                                                                    |
| `event_id`        | string (UUID)             | Unique identifier for this event - **equals the `Webhook-Id` header**, your [idempotency key](/webhooks/delivery#idempotency).                            |
| `event_type`      | string (open enum)        | What happened, e.g. `"transfer.received"`.                                                                                                                |
| `subscription_id` | string (UUID)             | The [subscription](/webhooks/overview) 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](#event-catalog).                                                           |

### Example

```json Example delivery (transfer.received) theme={null}
{
  "schema_version": "1.0",
  "event_id": "5b8e3c1a-9d27-4f60-b4e8-6a1c0d9f3b52",
  "event_type": "transfer.received",
  "subscription_id": "9b7c1e2a-4f6d-4c3b-8a1e-2d5f7a9c0b13",
  "occurred_at": "2026-05-26T14:22:48.123Z",
  "data": { ... }
}
```

### 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 `data` object. 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, the `data` schema, and example payloads.

### transfer.received

Fired once per incoming transfer to a watched address, when WalletSuite first observes it on-chain. The `data` 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](#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.    |

<Warning title="amount is a string - parse it with a decimal type">
  `amount` is a **decimal string in token units**, already adjusted for the asset's decimals. `"1.5"` means 1.5 tokens, not 1.5 wei. It is never in scientific notation and has arbitrary precision.

  Parse it with a decimal/big-number type (`decimal.Decimal`, `BigNumber`, `BigDecimal`), **never a native float** - IEEE-754 floats silently lose precision on values like USDC amounts and large token balances.
</Warning>

#### Example payloads

Four complete `transfer.received` payloads - one per asset shape.

<Tabs>
  <Tab title="Ethereum - native ETH">
    ```json ETH native transfer theme={null}
    {
      "schema_version": "1.0",
      "event_id": "5b8e3c1a-9d27-4f60-b4e8-6a1c0d9f3b52",
      "event_type": "transfer.received",
      "subscription_id": "9b7c1e2a-4f6d-4c3b-8a1e-2d5f7a9c0b13",
      "occurred_at": "2026-05-26T14:22:48.123Z",
      "data": {
        "chain": "ethereum",
        "direction": "incoming",
        "tx_hash": "0x9f3c1d8e7a2b4f6c0d9e8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7d",
        "block_number": 18573245,
        "from": "0x1234567890abcdef1234567890abcdef12345678",
        "to": "0xabcdef1234567890abcdef1234567890abcdef12",
        "amount": "1.5",
        "asset_type": "native",
        "asset_contract": null
      }
    }
    ```
  </Tab>

  <Tab title="Ethereum - ERC-20 (USDC)">
    ```json USDC (ERC-20) transfer theme={null}
    {
      "schema_version": "1.0",
      "event_id": "a1c4e8b0-2d6f-4a9b-91c3-7e0d5f8a2b46",
      "event_type": "transfer.received",
      "subscription_id": "9b7c1e2a-4f6d-4c3b-8a1e-2d5f7a9c0b13",
      "occurred_at": "2026-05-26T14:23:11.480Z",
      "data": {
        "chain": "ethereum",
        "direction": "incoming",
        "tx_hash": "0x4d2a7f9c1e3b6a8d0c5f2e4b7a9d1c3e5f8b0a2d4c6e8f0a1b3d5c7e9f2a4b6d",
        "block_number": 18573251,
        "from": "0x9876543210fedcba9876543210fedcba98765432",
        "to": "0xabcdef1234567890abcdef1234567890abcdef12",
        "amount": "250.000000",
        "asset_type": "erc20",
        "asset_contract": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
      }
    }
    ```
  </Tab>

  <Tab title="Tron - native TRX">
    ```json TRX native transfer theme={null}
    {
      "schema_version": "1.0",
      "event_id": "c7e2a9d4-5b8f-4c1a-83e6-1d4f7a0c9b25",
      "event_type": "transfer.received",
      "subscription_id": "2e9f1a7c-6b4d-4e8a-9c1f-3a5d7b0e2c84",
      "occurred_at": "2026-05-26T14:24:02.715Z",
      "data": {
        "chain": "tron",
        "direction": "incoming",
        "tx_hash": "5f0c8b3a1d6e9f2c4b7a0d5e8c1f3a6b9d2e4c7f0a3b6d9e1c4f7a0b3d6e9c2f",
        "block_number": 64218903,
        "from": "414a8f5c2b1d9e3a7c0f6b4d8e2a1c5f9b3d7e0a26",
        "to": "41c89e7f0a3b6d9e1c4f7a0b3d6e9c2f5a8b1d4e07",
        "amount": "1000.0",
        "asset_type": "native",
        "asset_contract": null
      }
    }
    ```
  </Tab>

  <Tab title="Tron - TRC-20 (USDT)">
    ```json USDT (TRC-20) transfer theme={null}
    {
      "schema_version": "1.0",
      "event_id": "e0b5d9a2-3c7f-4d6a-91b8-4f2a6c0d8e17",
      "event_type": "transfer.received",
      "subscription_id": "2e9f1a7c-6b4d-4e8a-9c1f-3a5d7b0e2c84",
      "occurred_at": "2026-05-26T14:25:37.902Z",
      "data": {
        "chain": "tron",
        "direction": "incoming",
        "tx_hash": "9c2f5a8b1d4e7a0b3d6e9c2f5f0c8b3a1d6e9f2c4b7a0d5e8c1f3a6b9d2e4c7f",
        "block_number": 64218947,
        "from": "414a8f5c2b1d9e3a7c0f6b4d8e2a1c5f9b3d7e0a26",
        "to": "41c89e7f0a3b6d9e1c4f7a0b3d6e9c2f5a8b1d4e07",
        "amount": "500.000000",
        "asset_type": "trc20",
        "asset_contract": "41a614f803b6fd780986a42c78ec9c7f77e6ded13c"
      }
    }
    ```
  </Tab>
</Tabs>

## 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`](#transferreceived) on the payload, not by inspecting `eventKinds` (which is never sent). See [Quickstart](/webhooks/quickstart) for creating subscriptions.

## Related

<CardGroup cols={2}>
  <Card title="Quickstart" icon="bolt" href="/webhooks/quickstart">
    Create a subscription, provision a signing secret, and receive your first event.
  </Card>

  <Card title="Verify Signatures" icon="shield-check" href="/webhooks/verify">
    Validate the Standard Webhooks signature against the raw request body.
  </Card>

  <Card title="Delivery & Retries" icon="arrows-rotate" href="/webhooks/delivery">
    Acknowledgement window, retry schedule, ordering, and at-least-once semantics.
  </Card>

  <Card title="Troubleshooting" icon="wrench" href="/webhooks/troubleshooting">
    When a payload fails to verify or never arrives - resolution checklists and FAQ.
  </Card>

  <Card title="Best Practices" icon="list-check" href="/webhooks/best-practices">
    Idempotency, async processing, and hardening your endpoint for production.
  </Card>
</CardGroup>
