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

# Event types

<Info>
  **Pre-release** — contact your Fortary account team for access.
</Info>

Every delivery's request body is an **event envelope**: a fixed outer shape plus a `data` payload specific to the event kind. Your webhook only receives the kinds it subscribed to.

## The event envelope

```json theme={null}
{
  "id": "evt_01hz8x2k9qv7m3ntf5rw6ye8ka",
  "kind": "transaction.confirmed",
  "schemaVersion": 1,
  "date": "2026-06-10T14:23:05Z",
  "entityId": "entity_7c1e4a0c2f",
  "vaultIds": ["vault_3f8a2c1d9b"],
  "data": { }
}
```

| Field           | Description                                                                                         |
| --------------- | --------------------------------------------------------------------------------------------------- |
| `id`            | Unique event id (`evt_…`). Stable across retries and redeliveries — **deduplicate on it**           |
| `kind`          | The event kind, `resource.action` (e.g. `transaction.confirmed`)                                    |
| `schemaVersion` | Integer version of this kind's `data` schema                                                        |
| `date`          | When the event occurred (not when it was delivered) — **order on it**                               |
| `entityId`      | The entity the event belongs to                                                                     |
| `vaultIds`      | Vaults involved; empty for non-vault-scoped kinds; can contain several vaults for UTXO transactions |
| `data`          | Kind-specific payload, documented below                                                             |

<Info>
  Asset amounts are **strings in atomic units**; `amountUsd` valuations are indicative JSON numbers. Timestamps are ISO-8601 UTC (`Z`), absent values are explicit `null`, and IDs are opaque prefixed strings — pass back exactly what you received.
</Info>

## Event kinds

| Kind                      | Fires when                                                                 |
| ------------------------- | -------------------------------------------------------------------------- |
| `transaction.requested`   | A transaction request is submitted and enters approval                     |
| `transaction.approved`    | The request passes its approval policy                                     |
| `transaction.rejected`    | The request is rejected by an approver                                     |
| `transaction.expired`     | The request expires before collecting the required approvals               |
| `transaction.broadcasted` | The transaction is submitted to the network and receives its on-chain hash |
| `transaction.confirmed`   | The transaction reaches the required confirmation depth                    |
| `transaction.failed`      | The transaction's on-chain execution fails                                 |
| `address.created`         | A deposit address is issued for a vault                                    |

## Transaction lifecycle

A custody transaction is correlated by `txRequestId` until broadcast and by `txHash` after it — `transaction.broadcasted` carries **both**:

```
transaction.requested ──► transaction.approved ──► transaction.broadcasted ──► transaction.confirmed
          │                                                            └─────► transaction.failed
          ├──► transaction.rejected
          └──► transaction.expired
```

Incoming deposits have no request phase — the first event you receive for a deposit is `transaction.confirmed`.

<Warning>
  **Credit funds only on `transaction.confirmed`.** Every earlier event is a pre-settlement observation.
</Warning>

### `transaction.requested`, `transaction.approved`, `transaction.rejected`, `transaction.expired`

The approval-phase events share one payload — the request's identity and network. Authoritative amounts arrive with `transaction.confirmed`.

```json theme={null}
{
  "id": "evt_01hz8vq4t2m9k7xw3nrf5ye8c2",
  "kind": "transaction.requested",
  "schemaVersion": 1,
  "date": "2026-06-10T14:02:11Z",
  "entityId": "entity_7c1e4a0c2f",
  "vaultIds": ["vault_3f8a2c1d9b"],
  "data": {
    "txRequestId": "9f4e6a2b-3c1d-4e8f-a501-2b7c9d0e1f23",
    "networkId": "eip155:43114"
  }
}
```

* **`txRequestId`** — the transaction request's identifier; also present on `transaction.broadcasted` for correlation.
* **`networkId`** — the network, as a [CAIP-2](https://chainagnostic.org/CAIPs/caip-2) id (e.g. `eip155:43114` for Avalanche C-Chain).

### `transaction.broadcasted`

Fires when the transaction is submitted to the network, joining the request-phase identity (`txRequestId`) to the on-chain identity (`txHash`). No amounts yet — nothing is decoded at broadcast time.

```json theme={null}
{
  "id": "evt_01hz8wr7p5n2j9ky4mtg6ze1d8",
  "kind": "transaction.broadcasted",
  "schemaVersion": 1,
  "date": "2026-06-10T14:08:42Z",
  "entityId": "entity_7c1e4a0c2f",
  "vaultIds": ["vault_3f8a2c1d9b"],
  "data": {
    "txRequestId": "9f4e6a2b-3c1d-4e8f-a501-2b7c9d0e1f23",
    "networkId": "eip155:43114",
    "txHash": "0x9c4f2ea1b83d5f7c6a01e9d24b8f3a5c7e610d92f48ab35c17ed09b64a2f8e31"
  }
}
```

### `transaction.confirmed` and `transaction.failed`

Both carry a full snapshot of the transaction as observed on-chain — the same shape, distinguished by `status`. Example: an incoming AVAX deposit —

```json theme={null}
{
  "id": "evt_01hz8x2k9qv7m3ntf5rw6ye8ka",
  "kind": "transaction.confirmed",
  "schemaVersion": 1,
  "date": "2026-06-10T14:23:05Z",
  "entityId": "entity_7c1e4a0c2f",
  "vaultIds": ["vault_3f8a2c1d9b"],
  "data": {
    "txHash": "0x2b7e91c04a6f8d3e5c19b0a7f42d68e3a5c901f7d84b26ea30fc59d18b47a6e2",
    "networkId": "eip155:43114",
    "blockNumber": 41234567,
    "timestamp": "2026-06-10T14:22:58Z",
    "status": "CONFIRMED",
    "amounts": [
      {
        "direction": "CREDIT",
        "asset": {
          "kind": "native",
          "assetId": "eip155:43114",
          "decimals": 18,
          "symbol": "AVAX",
          "name": "Avalanche",
          "logoUri": null
        },
        "amount": "1250000000000000000",
        "amountUsd": 31.25,
        "fromAddresses": ["0x1f0ec8b90a37f6d2f0e5b3a49c7d81f2e6a04b53"],
        "toAddresses": ["0x8ab34c1d9e2f5a706b8c3d4e5f6a7b8c9d0e1f2a"]
      }
    ],
    "fee": null,
    "flow": "incoming"
  }
}
```

* **`status`** — `CONFIRMED` or `FAILED`. `transaction.failed` is only delivered for outgoing transactions — a deposit that fails on-chain produces no event.
* **`amounts`** — one entry per asset movement touching your vaults. `direction` is `CREDIT` or `DEBIT`; `amount` is a string in the asset's atomic unit; `amountUsd` may be `null` when no price is available.
* **`asset`** — `kind: "native"` (`assetId` is the bare CAIP-2 network id) or `kind: "token"`, which adds `namespace` (`erc20` or `spl`) and `contractAddress`.
* **`fee`** — the network fee, or `null` when it wasn't paid by you (typical for deposits).
* **`flow`** — the transaction's direction relative to your vaults: `incoming`, `outgoing`, `internal`, or `trade`.
* **`blockNumber`** — may be `null` on networks without block-height semantics.

### `address.created`

Fires when a deposit address is issued. The vault is in the envelope's `vaultIds`.

```json theme={null}
{
  "id": "evt_01hz8y6m3wp8n4kv7qsx2ze9fb",
  "kind": "address.created",
  "schemaVersion": 1,
  "date": "2026-06-10T15:01:33Z",
  "entityId": "entity_7c1e4a0c2f",
  "vaultIds": ["vault_3f8a2c1d9b"],
  "data": {
    "networkId": "bip122:000000000019d6689c085ae165831e93",
    "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
  }
}
```

## Schema versioning

Each kind's `data` payload is versioned via `schemaVersion`. Additive changes ship under the same version — treat unknown fields as forward-compatible. Breaking changes increment the version and are announced in the [changelog](/api/changelog).
