> ## Documentation Index
> Fetch the complete documentation index at: https://rain-sandbox-trial.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Transaction Webhooks and History

> Where wallet activity shows up on the server side today, which existing webhooks cover it, what to poll during the beta, and which wallet events arrive at GA.

Wallet activity is visible in two places: on-chain, through the SDK's history in the app, and in Rain's systems, through the issuing API and webhooks, wherever the activity touches a card program. During the beta, the wallet itself emits no webhooks; this page tells you what to use instead, and how to build so that the wallet events arriving at GA drop in without rework.

## Two views of the same activity

| | In the app (SDK) | On your server (Rain API and webhooks) |
| - | - | - |
| Source | The chain, via your RPC endpoints, and Rain's wallet infrastructure | Rain's ledger |
| Covers | Every transfer in or out of the wallet, on any chain you registered | Activity that touches the card program: collateral deposits, card spend, settlement, refunds |
| Doesn't cover | Card authorizations and settlement (they don't move funds through the wallet) | Wallet-to-wallet transfers that never touch a collateral contract |
| Read with | `getTransactions(chainId:)`, `getBalance`, `getTokenBalances` | `GET /v1/issuing/transactions`, `GET /v1/issuing/users/{userId}/balances`, webhooks |

A deposit from the wallet into a collateral contract is the one event that appears in both: as an outgoing token transfer in the SDK's history, and as a `transaction.created` webhook of type `collateral` on your server.

## Existing webhooks that cover wallet flows

You don't need new subscriptions for the beta. These events, already in the [event catalog](/docs/event-catalog), carry the wallet-related state:

| Event | Fires when | Wallet-relevant fields |
| - | - | - |
| [`contract.created`](/docs/account-and-reports#contract-created) | Rain deploys a collateral contract for an approved user or company | `userAddress` (the owner wallet), `proxyAddress`, `depositAddress`, `controllerAddress`, `chainId` |
| [`transaction.created` (`collateral`)](/docs/transaction#collateral) | Collateral lands in a contract, from the wallet or anywhere else | `collateral.walletAddress` (sender), `collateral.transactionHash`, `collateral.amount`, `collateral.currency`, `collateral.chainId` |
| [`transaction.created` / `updated` / `completed` (`spend`)](/docs/transaction#spend) | A card transaction is authorized, changes, or settles | `fundMovements`, for tenants on the versions that include it: the on-chain pulls that backed the spend, with `hash` and `chainId` |
| [`user.updated`](/docs/identity-and-compliance#user-updated) | The user's application or KYC status changes | Gates when the contract will exist and card funding can begin |

To tie a `collateral` webhook back to a specific wallet send, match `collateral.transactionHash` to the `transactionHash` your app got from `sendToken`. `collateral.walletAddress` identifies the sending wallet, not the send: one wallet can make many deposits, so use it to attribute the deposit to a user or as a secondary check, never as the match key. Withdrawals from the contract don't have a dedicated webhook today; the app has the transaction hash from `withdrawCollateral`, and the contract's token balances in `GET /v1/issuing/users/{userId}/contracts` reflect the change.

## What to poll during the beta

<Info>
  **Beta: polling only.** Wallet-state events (wallet created, backup method added, key exported, passkey added, session events) aren't emitted during the beta. Wallet webhooks are a GA deliverable, and this section describes the interim approach.
</Info>

| You want to know | Poll | Cadence |
| - | - | - |
| A new wallet exists for a user | Your own backend: the app reports the address after `confirmLoginCode` / `signUpWithPasskey` | On event, from the app |
| A deposit reached the wallet | `getBalance` or `getTokenBalances` from the app; `getTransactions` for the row | 10–15 s while the deposit screen is visible |
| Collateral reached the contract | `transaction.created` (`collateral`) webhook; fallback `GET /v1/issuing/users/{userId}/contracts` | Webhook; poll every 30–60 s only as fallback |
| Spending power changed | `GET /v1/issuing/users/{userId}/balances` | After a collateral webhook, and on screen open |
| A withdrawal completed | `getTransactions` for the hash from `withdrawCollateral`, or a block explorer | Every few seconds until the hash appears |
| A user enrolled a backup method or exported keys | Record it in your backend from the app when the call succeeds | On event, from the app |

Keep the app as the source for wallet-side events and report them to your backend when they happen; that gives you an audit trail now and the same data shape you'll receive from webhooks later.

## What arrives at GA

GA adds real-time webhooks for wallet and transaction events, listed in the event catalog with a dedicated wallet webhooks page. Build your consumer so they slot in:

* **Use the standard envelope.** Every Rain webhook is `{ id, resource, action, version, body }`. Route on `resource` and `action` rather than on URL paths, and wallet events (a new `resource`) join without new plumbing. See [Webhooks](/docs/webhooks) and [Webhook delivery](/docs/webhook-delivery).
* **Key on addresses and hashes.** Store the wallet address and Rain `userId` together at sign-up, and store transaction hashes the app reports. Wallet events will reference these, so your reconciliation code doesn't change.
* **Keep polling behind an interface.** Put today's polling behind the same handler that will process the webhook so you can remove the poller without touching business logic.

## What's next

<Columns cols={2}>
  <Card title="Event catalog" icon="list" href="/docs/event-catalog">
    Every event, its category, and when it fires.
  </Card>

  <Card title="Balances and history" icon="clock-rotate-left" href="/docs/embedded-wallets/balances-and-history">
    The SDK side of the same activity.
  </Card>
</Columns>
