> ## 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 Events

> Track spend, collateral, payment, and transfer events across their full lifecycle.

Transaction webhooks notify your systems as money moves across spend,
collateral, and payment activity (`transaction` events) and transfers
(`transactionTransfer` events). Use them to reconcile activity and trigger
workflows in real time, without polling the API.

The following events are available:

| Event                                                             | Description                                                            |
| ----------------------------------------------------------------- | ---------------------------------------------------------------------- |
| [`transaction.requested`](#transaction-requested)                 | A cardholder attempts to authorize a purchase (spend).                 |
| [`transaction.created`](#transaction-created)                     | Rain creates a spend, collateral, or payment transaction.              |
| [`transaction.updated`](#transaction-updated)                     | A transaction changes, such as an incremental authorization or refund. |
| [`transaction.completed`](#transaction-completed)                 | A spend or payment transaction reaches a final, settled state.         |
| [`transactionTransfer.created`](#transactiontransfer-created)     | You initiate a transfer.                                               |
| [`transactionTransfer.updated`](#transactiontransfer-updated)     | A transfer changes state.                                              |
| [`transactionTransfer.completed`](#transactiontransfer-completed) | A transfer settles at the destination.                                 |

The two resources report amounts differently, so do not assume one convention across both. Every `spend` amount is an integer in cents: `5000` means \$50.00. Every `transactionTransfer` amount is a decimal string in the currency's major unit: `"1000.00"` means \$1,000.00. Collateral amounts follow the asset and can include decimals for native token amounts.

<Info>
  Spend transaction webhooks include an optional `eventReceivedAt` timestamp field. This field captures when Rain first received the event from the payment processor, which can help with debugging timing issues and building audit trails.

  By default, this field is excluded from webhook payloads. Contact your Rain account manager to enable it for your tenant.
</Info>

A single authorization moves through several states rather than firing once, and each state change is its own `transaction.*` event. The `transaction.created` event also covers payment and collateral transactions, while `transaction.completed` also covers payments. The `body` distinguishes the type.

<div className="wf-diagram">
  <div className="legend">
    <span className="lg"><span className="swatch send" />Webhook Rain sends you</span>
    <span className="lg"><span className="swatch handle" />Your handler (ack 2xx)</span>
    <span className="lg"><span className="swatch action" />Action / API call</span>
    <span className="lg"><span className="swatch ext" />Card network</span>
    <span className="lg"><span className="swatch cond" />Conditional step</span>
    <span className="lg"><span className="swatch disp" />Exception (dispute)</span>
  </div>

  <div className="diagram-shell">
    <svg id="flow-txn" role="img" aria-label="flow-txn swimlane" viewBox="0 0 1080 1324" width="1080" height="1324" style={{width: "100%", height: "auto"}}><defs><marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" className="marker-fill-default" /></marker><marker id="arrowSend" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" className="marker-fill-send" /></marker><marker id="arrowDisp" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" className="marker-fill-disp" /></marker></defs><text x="20" y="380" className="phase-label" transform="rotate(-90 20 380)" text-anchor="middle">Authorization</text><rect x="6" y="680" width="1068" height="300" className="phase-band" rx="9" /><text x="20" y="830" className="phase-label" transform="rotate(-90 20 830)" text-anchor="middle">Adjustments · 0..n</text><text x="20" y="1147" className="phase-label" transform="rotate(-90 20 1147)" text-anchor="middle">Clearing & settlement</text><line x1="138" y1="70" x2="138" y2="1312" className="lane-line" stroke-width="1.5" stroke-dasharray="2 6" /><line x1="416.6666666666667" y1="70" x2="416.6666666666667" y2="1312" className="lane-line" stroke-width="1.5" stroke-dasharray="2 6" /><line x1="695.3333333333334" y1="70" x2="695.3333333333334" y2="1312" className="lane-line" stroke-width="1.5" stroke-dasharray="2 6" /><line x1="974" y1="70" x2="974" y2="1312" className="lane-line" stroke-width="1.5" stroke-dasharray="2 6" /><path d="M 695.3333333333334 168 C 695.3333333333334 184, 416.6666666666667 184, 416.6666666666667 200" fill="none" className="conn-default" stroke-width="1.7" marker-end="url(#arrow)" opacity="0.92" /><path d="M 416.6666666666667 268 C 416.6666666666667 284, 138 284, 138 300" fill="none" className="conn-default" stroke-width="1.7" marker-end="url(#arrow)" opacity="0.92" /><path d="M 138 368 C 138 384, 974 384, 974 400" fill="none" className="conn-send" stroke-width="1.7" stroke-dasharray="5 4" marker-end="url(#arrowSend)" opacity="0.92" /><path d="M 974 468 C 974 484, 138 484, 138 500" fill="none" className="conn-default" stroke-width="1.7" marker-end="url(#arrow)" opacity="0.92" /><path d="M 138 568 C 138 584, 974 584, 974 600" fill="none" className="conn-send" stroke-width="1.7" stroke-dasharray="5 4" marker-end="url(#arrowSend)" opacity="0.92" /><path d="M 974 668 C 974 684, 416.6666666666667 684, 416.6666666666667 700" fill="none" className="conn-default" stroke-width="1.7" marker-end="url(#arrow)" opacity="0.92" /><path d="M 416.6666666666667 768 C 416.6666666666667 784, 138 784, 138 800" fill="none" className="conn-default" stroke-width="1.7" marker-end="url(#arrow)" opacity="0.92" /><path d="M 138 868 C 138 884, 974 884, 974 900" fill="none" className="conn-send" stroke-width="1.7" stroke-dasharray="5 4" marker-end="url(#arrowSend)" opacity="0.92" /><path d="M 974 968 C 974 984, 416.6666666666667 984, 416.6666666666667 1000" fill="none" className="conn-default" stroke-width="1.7" marker-end="url(#arrow)" opacity="0.92" /><path d="M 416.6666666666667 1068 C 416.6666666666667 1084, 138 1084, 138 1100" fill="none" className="conn-default" stroke-width="1.7" marker-end="url(#arrow)" opacity="0.92" /><path d="M 138 1168 C 138 1184, 974 1184, 974 1200" fill="none" className="conn-send" stroke-width="1.7" stroke-dasharray="5 4" marker-end="url(#arrowSend)" opacity="0.92" /><foreignObject x="44" y="16" width="188" height="54"><div className="lane-head rain"><span className="ico">🌧️</span><span className="nm">Rain (issuer · processor)</span></div></foreignObject><foreignObject x="322.6666666666667" y="16" width="188" height="54"><div className="lane-head"><span className="ico">🌐</span><span className="nm">Card network</span></div></foreignObject><foreignObject x="601.3333333333334" y="16" width="188" height="54"><div className="lane-head"><span className="ico">👤</span><span className="nm">Cardholder</span></div></foreignObject><foreignObject x="880" y="16" width="188" height="54"><div className="lane-head"><span className="ico">🖥️</span><span className="nm">Partner backend (you)</span></div></foreignObject><foreignObject x="601.3333333333334" y="100" width="188" height="68"><div className="card action"><span className="bn">1</span><span className="ct"><span className="tag">Cardholder</span><span className="lab">Make a purchase</span></span></div></foreignObject><foreignObject x="322.6666666666667" y="200" width="188" height="68"><div className="card ext"><span className="bn">2</span><span className="ct"><span className="tag">Network</span><span className="lab">Authorization request</span></span></div></foreignObject><foreignObject x="44" y="300" width="188" height="68"><div className="card send"><span className="bn">3</span><span className="ct"><span className="tag">Webhook · pending</span><span className="lab mono">transaction.requested</span></span></div></foreignObject><foreignObject x="880" y="400" width="188" height="68"><div className="card handle"><span className="bn">4</span><span className="ct"><span className="tag">Respond</span><span className="lab">Approve or decline</span></span></div></foreignObject><foreignObject x="44" y="500" width="188" height="68"><div className="card send"><span className="bn">5</span><span className="ct"><span className="tag">Webhook · authorized</span><span className="lab mono">transaction.created</span></span></div></foreignObject><foreignObject x="880" y="600" width="188" height="68"><div className="card handle"><span className="bn">6</span><span className="ct"><span className="tag">Handle</span><span className="lab">ack 2xx</span></span></div></foreignObject><foreignObject x="322.6666666666667" y="700" width="188" height="68"><div className="card ext"><span className="bn">7</span><span className="ct"><span className="tag">Network</span><span className="lab">Reversal / adjustment</span></span></div></foreignObject><foreignObject x="44" y="800" width="188" height="68"><div className="card send cond"><span className="bn">8</span><span className="ct"><span className="tag">Webhook · 0..n</span><span className="lab mono">transaction.updated</span></span></div></foreignObject><foreignObject x="880" y="900" width="188" height="68"><div className="card handle cond"><span className="bn">9</span><span className="ct"><span className="tag">Handle</span><span className="lab">ack 2xx</span></span></div></foreignObject><foreignObject x="322.6666666666667" y="1000" width="188" height="68"><div className="card ext"><span className="bn">10</span><span className="ct"><span className="tag">Network</span><span className="lab">Clearing / presentment</span></span></div></foreignObject><foreignObject x="44" y="1100" width="188" height="68"><div className="card send"><span className="bn">11</span><span className="ct"><span className="tag">Webhook · settled</span><span className="lab mono">transaction.completed</span></span></div></foreignObject><foreignObject x="880" y="1200" width="188" height="68"><div className="card handle"><span className="bn">12</span><span className="ct"><span className="tag">Handle</span><span className="lab">ack 2xx</span></span></div></foreignObject></svg>
  </div>
</div>

## `transaction.requested`

Rain sends this webhook when an authorization request comes in for a transaction, such as a new purchase or an incremental authorization on an existing transaction.

### `spend`

Rain triggers the `spend` webhook when a cardholder spends their card. [Partner-managed programs](/docs/authorization-partner-managed) need to put a hold on the collateral balance and respond to this webhook to authorize the transaction. You do not need to persist this information.

```json Payload theme={null}
{
    "resource": "transaction",
    "action": "requested",
    "version": "1.1.0",
    "body": {
        "id": "txn_abc123",
        "type": "spend",
        "spend": {
            "amount": 7500,
            "currency": "usd",
            "localAmount": 6750,
            "localCurrency": "EUR",
            "authorizedAmount": 2500,
            "previouslyAuthorizedAmount": 5000,
            "merchantName": "HOTEL MARRIOTT",
            "merchantCity": "New York",
            "merchantCountry": "US",
            "merchantCategory": "Hotels and Motels",
            "merchantCategoryCode": "7011",
            "cardId": "card_123",
            "cardType": "virtual",
            "companyId": "company_456",
            "userId": "user_789",
            "userFirstName": "John",
            "userLastName": "Doe",
            "userEmail": "john.doe@example.com",
            "status": "pending",
            "authorizedAt": "2026-01-27T15:30:00.000Z",
            "exchangeRate": 1.11
        }
    }
}
```

| Field                              | Type                 | Description                                                             |
| ---------------------------------- | -------------------- | ----------------------------------------------------------------------- |
| `id`                               | `string`             | The transaction ID                                                      |
| `type`                             | `string`             | Always `spend` for this webhook                                         |
| `spend.amount`                     | `number`             | Transaction amount in USD cents                                         |
| `spend.currency`                   | `string`             | Currency code (for example, `usd`)                                      |
| `spend.localAmount`                | `number` (optional)  | Transaction amount in local currency                                    |
| `spend.localCurrency`              | `string` (optional)  | Local currency code                                                     |
| `spend.authorizedAmount`           | `number`             | The requested authorization amount                                      |
| `spend.authorizationMethod`        | `string` (optional)  | Method of authorization                                                 |
| `spend.previouslyAuthorizedAmount` | `number`             | The amount that was previously authorized                               |
| `spend.tokenizedSource`            | `string` (optional)  | Source of tokenization (for example, `apple_pay`, `google_pay`)         |
| `spend.merchantName`               | `string`             | Merchant name                                                           |
| `spend.merchantCity`               | `string`             | Merchant city                                                           |
| `spend.merchantCountry`            | `string`             | Merchant country                                                        |
| `spend.merchantCategory`           | `string`             | Merchant category description                                           |
| `spend.merchantCategoryCode`       | `string`             | Merchant category code (MCC)                                            |
| `spend.merchantId`                 | `string` (optional)  | Merchant ID                                                             |
| `spend.cardId`                     | `string`             | The card ID used for the transaction                                    |
| `spend.cardType`                   | `string`             | The card type (`virtual` or `physical`)                                 |
| `spend.companyId`                  | `string` (optional)  | Company ID (for corporate cards)                                        |
| `spend.userId`                     | `string`             | The user ID                                                             |
| `spend.userFirstName`              | `string`             | User's first name                                                       |
| `spend.userLastName`               | `string` (optional)  | User's last name                                                        |
| `spend.userEmail`                  | `string`             | User's email                                                            |
| `spend.status`                     | `string`             | Always `pending` for this webhook                                       |
| `spend.authorizedAt`               | `string`             | ISO 8601 timestamp of authorization                                     |
| `spend.signature`                  | `string` (optional)  | Signature for verification                                              |
| `spend.timestamp`                  | `number` (optional)  | Unix timestamp                                                          |
| `spend.exchangeRate`               | `number` (optional)  | Exchange rate applied                                                   |
| `spend.iso8583.de41`               | `string` (optional)  | Terminal ID (ISO 8583 Data Element 41)                                  |
| `spend.threeDSecure`               | `boolean` (optional) | Indicates whether 3D Secure authentication was used for the transaction |

### Response

<Warning>
  **Limited availability:**

  Only Partner-managed programs can authorize or reject transactions. Rain-managed programs do not support this feature at this time.
</Warning>

* Respond with `200 OK` (or any `2xx`) to approve the transaction.
* Respond with any non-`2xx` status code to reject it.

You can return a JSON body to confirm the decision and, when declining, include a rejection code:

<CodeGroup>
  ```json Approve theme={null}
  {
    "success": true
  }
  ```

  ```json Decline theme={null}
  {
    "success": false,
    "rejectionCode": "INSUFFICIENT_FUNDS"
  }
  ```
</CodeGroup>

The `rejectionCode` must be one of these exact values; anything else is recorded as `UNKNOWN`:

| Value                    | Meaning                                                |
| ------------------------ | ------------------------------------------------------ |
| `INSUFFICIENT_FUNDS`     | The user doesn't have the funds for this authorization |
| `SUSPICIOUS_TRANSACTION` | You suspect fraud                                      |
| `NOT_PERMITTED`          | The transaction violates your program's rules          |
| `UNKNOWN`                | Any other reason                                       |

## `transaction.created`

Rain sends this webhook whenever it creates a transaction.

### `collateral`

Rain sends the `collateral` webhook when a user or company adds collateral to their contract. For standard collateral contracts, these transactions are final, and Rain does not send an additional `completed` webhook.

For payment-type contracts (where Rain treats deposits as payments rather than collateral backing), Rain also sends a `transaction.completed` webhook with `type: "payment"` when the deposit posts. Contact your Rain account manager to determine your contract configuration.

```json Payload theme={null}
{
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "resource": "transaction",
    "action": "created",
    "version": "1.1.0",
    "body": {
        "id": "txn_abc123",
        "type": "collateral",
        "collateral": {
            "amount": 100000,
            "currency": "usdc",
            "chainId": 1,
            "walletAddress": "0x1234567890abcdef1234567890abcdef12345678",
            "transactionHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
            "companyId": "company_456",
            "postedAt": "2026-01-27T15:30:00.000Z",
            "contractAddress": "0x9876543210fedcba9876543210fedcba98765432"
        }
    }
}
```

| Field                        | Type                | Description                                                       |
| ---------------------------- | ------------------- | ----------------------------------------------------------------- |
| `id`                         | `string`            | The transaction ID                                                |
| `type`                       | `string`            | Always `collateral` for this webhook                              |
| `collateral.amount`          | `number`            | Collateral amount (may include decimals for native token amounts) |
| `collateral.currency`        | `string`            | Asset name in lowercase (for example, `usdc`, `usdt`)             |
| `collateral.chainId`         | `number`            | Blockchain chain ID (for example, `1` for Ethereum mainnet)       |
| `collateral.walletAddress`   | `string`            | Wallet address the collateral was sent from                       |
| `collateral.transactionHash` | `string`            | On-chain transaction hash                                         |
| `collateral.companyId`       | `string` (optional) | Company ID (for corporate accounts)                               |
| `collateral.userId`          | `string` (optional) | User ID (for consumer accounts)                                   |
| `collateral.postedAt`        | `string`            | ISO 8601 timestamp when the collateral was posted on-chain        |
| `collateral.contractAddress` | `string`            | The collateral contract address holding the funds                 |

### `spend`

Rain sends the `spend` webhook when it creates a transaction, whether the network authorizes or declines it. You must persist this information.

```json Payload theme={null}
{
    "resource": "transaction",
    "action": "created",
    "version": "1.2.0",
    "body": {
        "id": "txn_abc123",
        "type": "spend",
        "spend": {
            "amount": 5000,
            "currency": "usd",
            "localAmount": 4500,
            "localCurrency": "EUR",
            "authorizedAmount": 5000,
            "merchantName": "AMAZON",
            "merchantCity": "Seattle",
            "merchantCountry": "US",
            "merchantCategory": "Online Shopping",
            "merchantCategoryCode": "5411",
            "cardId": "card_123",
            "cardType": "virtual",
            "companyId": "company_456",
            "userId": "user_789",
            "userFirstName": "John",
            "userLastName": "Doe",
            "userEmail": "john.doe@example.com",
            "status": "pending",
            "authorizedAt": "2026-01-27T15:30:00.000Z",
            "exchangeRate": 1.11,
            "threeDSecure": true
        }
    }
}
```

| Field                        | Type                 | Description                                                                                                                                                               |
| ---------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                         | `string`             | The transaction ID                                                                                                                                                        |
| `type`                       | `string`             | Always `spend` for this webhook                                                                                                                                           |
| `spend.amount`               | `number`             | Transaction amount in USD cents                                                                                                                                           |
| `spend.currency`             | `string`             | Currency code (for example, `usd`)                                                                                                                                        |
| `spend.localAmount`          | `number` (optional)  | Transaction amount in local currency                                                                                                                                      |
| `spend.localCurrency`        | `string` (optional)  | Local currency code                                                                                                                                                       |
| `spend.authorizedAmount`     | `number` (optional)  | The authorized amount                                                                                                                                                     |
| `spend.authorizationMethod`  | `string` (optional)  | Method of authorization                                                                                                                                                   |
| `spend.merchantName`         | `string`             | Merchant name                                                                                                                                                             |
| `spend.merchantCity`         | `string`             | Merchant city                                                                                                                                                             |
| `spend.merchantCountry`      | `string`             | Merchant country                                                                                                                                                          |
| `spend.merchantCategory`     | `string`             | Merchant category description                                                                                                                                             |
| `spend.merchantCategoryCode` | `string`             | Merchant category code (MCC)                                                                                                                                              |
| `spend.merchantId`           | `string` (optional)  | Merchant ID                                                                                                                                                               |
| `spend.cardId`               | `string`             | The card ID used for the transaction                                                                                                                                      |
| `spend.cardType`             | `string`             | The card type (`virtual` or `physical`)                                                                                                                                   |
| `spend.companyId`            | `string` (optional)  | Company ID (for corporate cards)                                                                                                                                          |
| `spend.userId`               | `string`             | The user ID                                                                                                                                                               |
| `spend.userFirstName`        | `string`             | User's first name                                                                                                                                                         |
| `spend.userLastName`         | `string` (optional)  | User's last name                                                                                                                                                          |
| `spend.userEmail`            | `string`             | User's email                                                                                                                                                              |
| `spend.status`               | `string`             | Transaction status (`pending` or `declined`)                                                                                                                              |
| `spend.declinedReason`       | `string` (optional)  | Reason for decline (only when status is `declined`)                                                                                                                       |
| `spend.authorizedAt`         | `string`             | ISO 8601 timestamp of authorization                                                                                                                                       |
| `spend.signature`            | `string` (optional)  | Signature for verification                                                                                                                                                |
| `spend.timestamp`            | `number` (optional)  | Unix timestamp                                                                                                                                                            |
| `spend.exchangeRate`         | `number` (optional)  | The exchange rate used to convert the local transaction amount to the settlement amount (USD). Present for international transactions where currency conversion occurred. |
| `spend.threeDSecure`         | `boolean` (optional) | Indicates whether 3D Secure authentication was used for the transaction                                                                                                   |
| `spend.iso8583.de41`         | `string` (optional)  | Terminal ID (ISO 8583 Data Element 41)                                                                                                                                    |
| `spend.tokenizedSource`      | `string` (optional)  | Source of tokenization (for example, `apple_pay`, `google_pay`)                                                                                                           |
| `spend.fundMovements`        | `array` (optional)   | On-chain fund movements backing the transaction, ordered oldest first. Requires `transaction.created` version `1.3.0` or later. See [Fund movements](#fund-movements).    |

### `payment`

Rain sends the `payment` webhook when you initiate a payment on-chain. Rain sends a separate webhook when the payment completes.

```json Payload theme={null}
{
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "resource": "transaction",
    "action": "created",
    "version": "1.0.0",
    "body": {
        "id": "txn_abc123",
        "type": "payment",
        "payment": {
            "amount": 50000,
            "currency": "usd",
            "chainId": 1,
            "walletAddress": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
            "transactionHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
            "companyId": "company_456",
            "status": "pending"
        }
    }
}
```

| Field                     | Type                | Description                                                          |
| ------------------------- | ------------------- | -------------------------------------------------------------------- |
| `id`                      | `string`            | The transaction ID                                                   |
| `type`                    | `string`            | Always `payment` for this webhook                                    |
| `payment.amount`          | `number`            | Payment amount                                                       |
| `payment.currency`        | `string`            | Currency code (for example, `usd`)                                   |
| `payment.chainId`         | `number`            | Blockchain chain ID (for example, `1` for Ethereum mainnet)          |
| `payment.walletAddress`   | `string`            | Wallet address the payment was sent from (EIP-55 checksummed format) |
| `payment.transactionHash` | `string`            | On-chain transaction hash                                            |
| `payment.companyId`       | `string` (optional) | Company ID (for corporate accounts)                                  |
| `payment.userId`          | `string` (optional) | User ID (for consumer accounts)                                      |
| `payment.status`          | `string`            | Always `pending` for this webhook                                    |

## `transaction.updated`

Rain sends this webhook whenever it updates a transaction. The transaction may not exist yet when this update arrives.

### `spend`

Rain triggers this webhook for events such as incremental authorizations or refunds.

```json Payload theme={null}
{
    "resource": "transaction",
    "action": "updated",
    "version": "1.1.0",
    "body": {
        "id": "txn_abc123",
        "type": "spend",
        "spend": {
            "amount": 5000,
            "currency": "usd",
            "merchantName": "SUSPICIOUS MERCHANT",
            "merchantCity": "Unknown",
            "merchantCountry": "XX",
            "merchantCategory": "Miscellaneous",
            "merchantCategoryCode": "9999",
            "cardId": "card_123",
            "cardType": "virtual",
            "userId": "user_789",
            "userFirstName": "John",
            "userLastName": "Doe",
            "userEmail": "john.doe@example.com",
            "status": "declined",
            "declinedReason": "suspected fraud",
            "authorizedAt": "2026-01-27T15:30:00.000Z"
        }
    }
}
```

| Field                             | Type                | Description                                                                                                                                                               |
| --------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                              | `string`            | The transaction ID                                                                                                                                                        |
| `type`                            | `string`            | Always `spend` for this webhook                                                                                                                                           |
| `spend.amount`                    | `number`            | Transaction amount in USD cents                                                                                                                                           |
| `spend.currency`                  | `string`            | Currency code (for example, `usd`)                                                                                                                                        |
| `spend.localAmount`               | `number` (optional) | Transaction amount in local currency                                                                                                                                      |
| `spend.localCurrency`             | `string` (optional) | Local currency code                                                                                                                                                       |
| `spend.authorizedAmount`          | `number` (optional) | The authorized amount                                                                                                                                                     |
| `spend.authorizationUpdateAmount` | `number` (optional) | The amount by which the authorization changed                                                                                                                             |
| `spend.authorizationMethod`       | `string` (optional) | Method of authorization                                                                                                                                                   |
| `spend.merchantName`              | `string`            | Merchant name                                                                                                                                                             |
| `spend.merchantCity`              | `string`            | Merchant city                                                                                                                                                             |
| `spend.merchantCountry`           | `string`            | Merchant country                                                                                                                                                          |
| `spend.merchantCategory`          | `string`            | Merchant category description                                                                                                                                             |
| `spend.merchantCategoryCode`      | `string`            | Merchant category code (MCC)                                                                                                                                              |
| `spend.merchantId`                | `string` (optional) | Merchant ID                                                                                                                                                               |
| `spend.cardId`                    | `string`            | The card ID used for the transaction                                                                                                                                      |
| `spend.cardType`                  | `string`            | The card type (`virtual` or `physical`)                                                                                                                                   |
| `spend.companyId`                 | `string` (optional) | Company ID (for corporate cards)                                                                                                                                          |
| `spend.userId`                    | `string`            | The user ID                                                                                                                                                               |
| `spend.userFirstName`             | `string`            | User's first name                                                                                                                                                         |
| `spend.userLastName`              | `string` (optional) | User's last name                                                                                                                                                          |
| `spend.userEmail`                 | `string`            | User's email                                                                                                                                                              |
| `spend.status`                    | `string`            | Transaction status (`pending`, `reversed`, or `declined`)                                                                                                                 |
| `spend.declinedReason`            | `string` (optional) | Reason for decline (only when status is `declined`)                                                                                                                       |
| `spend.authorizedAt`              | `string`            | ISO 8601 timestamp of authorization                                                                                                                                       |
| `spend.signature`                 | `string` (optional) | Signature for verification                                                                                                                                                |
| `spend.timestamp`                 | `number` (optional) | Unix timestamp                                                                                                                                                            |
| `spend.enrichedMerchantName`      | `string` (optional) | The enriched (cleaned-up) name of the merchant                                                                                                                            |
| `spend.enrichedMerchantCategory`  | `string` (optional) | The enriched (cleaned-up) category of the merchant                                                                                                                        |
| `spend.enrichedMerchantIcon`      | `string` (optional) | URL of the enriched merchant's icon                                                                                                                                       |
| `spend.iso8583.de41`              | `string` (optional) | Terminal ID (ISO 8583 Data Element 41)                                                                                                                                    |
| `spend.exchangeRate`              | `number` (optional) | The exchange rate used to convert the local transaction amount to the settlement amount (USD). Present for international transactions where currency conversion occurred. |
| `spend.fundMovements`             | `array` (optional)  | On-chain fund movements backing the transaction, ordered oldest first. Requires `transaction.updated` version `1.2.0` or later. See [Fund movements](#fund-movements).    |

The `status` field can take these values:

| Status     | Description                                                  |
| ---------- | ------------------------------------------------------------ |
| `pending`  | Transaction is still pending settlement                      |
| `reversed` | Authorization was reversed (for example, voided by merchant) |
| `declined` | Transaction was declined after initial authorization         |

## `transaction.completed`

Rain sends this webhook once, when a transaction first closes. If further network messages arrive for a transaction that has already closed, Rain does not send a second `transaction.completed`, so you can reconcile on this event as the single settlement signal. The transaction may not exist yet when this update arrives.

### `spend`

Rain sends the `spend` webhook when a transaction settles. No response is required.

```json Payload theme={null}
{
    "resource": "transaction",
    "action": "completed",
    "version": "1.3.0",
    "body": {
        "id": "txn_abc123",
        "type": "spend",
        "spend": {
            "amount": 5500,
            "currency": "usd",
            "localAmount": 4950,
            "localCurrency": "EUR",
            "authorizedAmount": 5000,
            "merchantName": "RESTAURANT XYZ",
            "merchantCity": "Miami",
            "merchantCountry": "US",
            "merchantCategory": "Restaurants",
            "merchantCategoryCode": "5812",
            "cardId": "card_123",
            "cardType": "physical",
            "companyId": "company_456",
            "userId": "user_789",
            "userFirstName": "John",
            "userLastName": "Doe",
            "userEmail": "john.doe@example.com",
            "status": "completed",
            "authorizedAt": "2026-01-27T19:30:00.000Z",
            "postedAt": "2026-01-29T08:15:00.000Z",
            "exchangeRate": 1.11,
            "completionReason": "settlement",
            "isForcePosted": true,
            "closedAuthorizationTransactionId": "txn_auth456",
            "threeDSecure": true
        }
    }
}
```

| Field                                    | Type                 | Description                                                                                                                                                               |
| ---------------------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                                     | `string`             | The transaction ID                                                                                                                                                        |
| `type`                                   | `string`             | Always `spend` for this webhook                                                                                                                                           |
| `spend.amount`                           | `number`             | Final settled transaction amount in USD cents                                                                                                                             |
| `spend.currency`                         | `string`             | Currency code (for example, `usd`)                                                                                                                                        |
| `spend.localAmount`                      | `number` (optional)  | Transaction amount in local currency                                                                                                                                      |
| `spend.localCurrency`                    | `string` (optional)  | Local currency code                                                                                                                                                       |
| `spend.authorizedAmount`                 | `number` (optional)  | The original authorized amount                                                                                                                                            |
| `spend.authorizationMethod`              | `string` (optional)  | Method of authorization                                                                                                                                                   |
| `spend.merchantName`                     | `string`             | Merchant name                                                                                                                                                             |
| `spend.merchantCity`                     | `string`             | Merchant city                                                                                                                                                             |
| `spend.merchantCountry`                  | `string`             | Merchant country                                                                                                                                                          |
| `spend.merchantCategory`                 | `string`             | Merchant category description                                                                                                                                             |
| `spend.merchantCategoryCode`             | `string`             | Merchant category code (MCC)                                                                                                                                              |
| `spend.merchantId`                       | `string` (optional)  | Merchant ID                                                                                                                                                               |
| `spend.cardId`                           | `string`             | The card ID used for the transaction                                                                                                                                      |
| `spend.cardType`                         | `string`             | The card type (`virtual` or `physical`)                                                                                                                                   |
| `spend.companyId`                        | `string` (optional)  | Company ID (for corporate cards)                                                                                                                                          |
| `spend.userId`                           | `string`             | The user ID                                                                                                                                                               |
| `spend.userFirstName`                    | `string`             | User's first name                                                                                                                                                         |
| `spend.userLastName`                     | `string` (optional)  | User's last name                                                                                                                                                          |
| `spend.userEmail`                        | `string`             | User's email                                                                                                                                                              |
| `spend.status`                           | `string`             | Always `completed` for this webhook                                                                                                                                       |
| `spend.authorizedAt`                     | `string`             | ISO 8601 timestamp of original authorization                                                                                                                              |
| `spend.postedAt`                         | `string`             | ISO 8601 timestamp when the transaction was posted or settled                                                                                                             |
| `spend.signature`                        | `string` (optional)  | Signature for verification                                                                                                                                                |
| `spend.timestamp`                        | `number` (optional)  | Unix timestamp                                                                                                                                                            |
| `spend.exchangeRate`                     | `number` (optional)  | The exchange rate used to convert the local transaction amount to the settlement amount (USD). Present for international transactions where currency conversion occurred. |
| `spend.completionReason`                 | `string` (optional)  | The reason the transaction was completed                                                                                                                                  |
| `spend.isForcePosted`                    | `boolean` (optional) | Indicates whether this transaction was force posted. Present when the value is explicitly `true` or `false`.                                                              |
| `spend.closedAuthorizationTransactionId` | `string` (optional)  | The ID of the authorization transaction that was closed when this force-posted settlement arrived. Present only when the force post closed an existing authorization.     |
| `spend.enrichedMerchantName`             | `string` (optional)  | The enriched (cleaned-up) name of the merchant                                                                                                                            |
| `spend.enrichedMerchantCategory`         | `string` (optional)  | The enriched (cleaned-up) category of the merchant                                                                                                                        |
| `spend.enrichedMerchantIcon`             | `string` (optional)  | URL of the enriched merchant's icon                                                                                                                                       |
| `spend.threeDSecure`                     | `boolean` (optional) | Indicates whether 3D Secure authentication was used for the transaction                                                                                                   |
| `spend.fundMovements`                    | `array` (optional)   | On-chain fund movements backing the transaction, ordered oldest first. Requires `transaction.completed` version `1.4.0` or later. See [Fund movements](#fund-movements).  |

The `completionReason` field can take these values:

| Value                         | Description                                              |
| ----------------------------- | -------------------------------------------------------- |
| `settlement`                  | Normal settlement from the payment network               |
| `stale_authorization_closure` | Authorization expired due to age without settlement      |
| `authorization_reversal`      | Merchant fully reversed the authorization amount to zero |
| `refund`                      | Transaction was refunded                                 |
| `chargeback`                  | Transaction was charged back                             |
| `manual_closure`              | Manually closed by an administrator                      |
| `reprocessed_settlement`      | Replayed force-posted settlement                         |

<Info>
  The `localAmount` and `localCurrency` fields are populated when the transaction involves a foreign currency or when it is a standard settlement where the authorized amount equals the final settled amount. These fields may be `undefined` in certain scenarios, such as partial captures where the authorized and settled amounts differ.
</Info>

### `payment`

Rain sends the `payment` webhook when an initiated on-chain payment completes.

```json Payload theme={null}
{
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "resource": "transaction",
    "action": "completed",
    "version": "1.0.0",
    "body": {
        "id": "txn_abc123",
        "type": "payment",
        "payment": {
            "amount": 50000,
            "currency": "usd",
            "chainId": 1,
            "walletAddress": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
            "transactionHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
            "companyId": "company_456",
            "status": "completed",
            "postedAt": "2026-01-27T16:45:00.000Z"
        }
    }
}
```

| Field                     | Type                | Description                                                          |
| ------------------------- | ------------------- | -------------------------------------------------------------------- |
| `id`                      | `string`            | The transaction ID                                                   |
| `type`                    | `string`            | Always `payment` for this webhook                                    |
| `payment.amount`          | `number`            | Payment amount                                                       |
| `payment.currency`        | `string`            | Currency code (for example, `usd`)                                   |
| `payment.chainId`         | `number`            | Blockchain chain ID (for example, `1` for Ethereum mainnet)          |
| `payment.walletAddress`   | `string`            | Wallet address the payment was sent from (EIP-55 checksummed format) |
| `payment.transactionHash` | `string`            | On-chain transaction hash                                            |
| `payment.companyId`       | `string` (optional) | Company ID (for corporate accounts)                                  |
| `payment.userId`          | `string` (optional) | User ID (for consumer accounts)                                      |
| `payment.status`          | `string`            | Always `completed` for this webhook                                  |
| `payment.postedAt`        | `string`            | ISO 8601 timestamp when the payment was posted or settled            |

## `transactionTransfer.created`

Rain sends this webhook whenever it creates a transfer transaction.

### `transfer`

Rain sends the `transfer` webhook when you initiate a new transfer. Rain sends a separate webhook when the transfer completes.

```json Payload theme={null}
{
    "resource": "transactionTransfer",
    "action": "created",
    "version": "1.0.0",
    "body": {
        "id": "txn_abc123",
        "type": "transfer",
        "transfer": {
            "userId": "usr_789xyz",
            "source": {
                "amount": "1000.00",
                "currency": "usdc",
                "rail": "onchain",
                "address": {
                    "type": "onchain",
                    "address": "0x1234567890abcdef1234567890abcdef12345678"
                }
            },
            "destination": {
                "amount": "998.50",
                "currency": "usd",
                "rail": "wire",
                "address": {
                    "type": "paymentAccount",
                    "id": "pa_456def"
                }
            },
            "fees": {
                "rain": { "currency": "usd", "amount": "1.00", "amountUSD": "1.00" },
                "developer": { "currency": "usd", "amount": "0.50", "amountUSD": "0.50" }
            },
            "exchangeRate": 1.0,
            "status": "pending",
            "createdAt": "2026-01-27T15:30:00.000Z",
            "updatedAt": "2026-01-27T15:30:00.000Z",
            "quoteId": "355e0a5c-76a5-4d13-bcee-f2ad39abe710",
            "expiresAt": "2026-01-28T15:30:00.000Z"
        }
    }
}
```

All three `transactionTransfer` events carry the same `transfer` object. The `status` and which optional fields are present vary by lifecycle stage.

| Field                              | Type                | Description                                                                                                                                                                                                                                    |
| ---------------------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                               | `string`            | The transaction ID                                                                                                                                                                                                                             |
| `type`                             | `string`            | Always `transfer` for this webhook                                                                                                                                                                                                             |
| `transfer.userId`                  | `string` (optional) | The user ID for consumer accounts                                                                                                                                                                                                              |
| `transfer.companyId`               | `string` (optional) | The company ID for corporate accounts                                                                                                                                                                                                          |
| `transfer.source.amount`           | `string`            | Source amount as a decimal string (for example, `"100.00"`)                                                                                                                                                                                    |
| `transfer.source.currency`         | `string`            | Source currency code                                                                                                                                                                                                                           |
| `transfer.source.rail`             | `string`            | Source rail (for example, `onchain`, `wire`)                                                                                                                                                                                                   |
| `transfer.source.referenceId`      | `string` (optional) | Source reference ID                                                                                                                                                                                                                            |
| `transfer.source.address`          | `object` (optional) | Source address (see [address types](#address-types))                                                                                                                                                                                           |
| `transfer.destination.amount`      | `string` (optional) | Destination amount as a decimal string                                                                                                                                                                                                         |
| `transfer.destination.currency`    | `string`            | Destination currency code                                                                                                                                                                                                                      |
| `transfer.destination.rail`        | `string`            | Destination rail                                                                                                                                                                                                                               |
| `transfer.destination.referenceId` | `string` (optional) | Destination reference ID                                                                                                                                                                                                                       |
| `transfer.destination.address`     | `object` (optional) | Destination address (see [address types](#address-types))                                                                                                                                                                                      |
| `transfer.depositAddress`          | `object` (optional) | Deposit address for the transfer (see [deposit address types](#deposit-address-types))                                                                                                                                                         |
| `transfer.fees.rain.currency`      | `string`            | Currency of Rain's fee                                                                                                                                                                                                                         |
| `transfer.fees.rain.amount`        | `string`            | Rain's fee amount as a decimal string                                                                                                                                                                                                          |
| `transfer.fees.rain.amountUSD`     | `string`            | Rain's fee amount in USD as a decimal string                                                                                                                                                                                                   |
| `transfer.fees.sender`             | `object` (optional) | [Sender fee](/docs/sender-fees) you configured, with the same `currency`, `amount`, and `amountUSD` shape. Present on transfers with a sender fee.                                                                                             |
| `transfer.fees.developer`          | `object` (optional) | Deprecated alias of `fees.sender`; read `sender` instead. Same `currency`, `amount`, and `amountUSD` shape.                                                                                                                                    |
| `transfer.exchangeRate`            | `number` (optional) | Exchange rate applied                                                                                                                                                                                                                          |
| `transfer.status`                  | `string`            | Transfer status at creation. Always `pending` or `awaiting_transfer`, the values that describe a transfer that hasn't started processing yet.                                                                                                  |
| `transfer.createdAt`               | `string`            | ISO 8601 timestamp of creation                                                                                                                                                                                                                 |
| `transfer.updatedAt`               | `string`            | ISO 8601 timestamp of last update                                                                                                                                                                                                              |
| `transfer.quoteId`                 | `string`            | The quote ID this transfer was created from                                                                                                                                                                                                    |
| `transfer.expiresAt`               | `string`            | ISO 8601 timestamp of when the transfer expires                                                                                                                                                                                                |
| `transfer.refundReason`            | `string` (optional) | Why the transfer was refunded: `limit_exceeded`, `invalid_destination`, `returned_by_bank`, `expired`, `amount_mismatch`, or `other`. Present only on refunded transfers, and some refunds carry no reason. Requires version `1.1.0` or later. |

## `transactionTransfer.updated`

Rain sends this webhook whenever a transfer's status changes after creation, except when it reaches `settled`.

### `transfer`

Rain sends the `transfer` webhook when a transfer's status changes after creation, including non-success terminal states (`failed`, `cancelled`, `expired`, `refunded`).

```json Payload theme={null}
{
    "resource": "transactionTransfer",
    "action": "updated",
    "version": "1.0.0",
    "body": {
        "id": "txn_abc123",
        "type": "transfer",
        "transfer": {
            "source": {
                "amount": "1000.00",
                "currency": "usdc",
                "rail": "onchain",
                "referenceId": "ref_123",
                "address": {
                    "type": "onchain",
                    "address": "0x1234567890abcdef1234567890abcdef12345678"
                }
            },
            "destination": {
                "amount": "998.50",
                "currency": "usd",
                "rail": "wire",
                "address": {
                    "type": "paymentAccount",
                    "id": "pa_456def"
                }
            },
            "fees": {
                "rain": { "currency": "usd", "amount": "1.00", "amountUSD": "1.00" },
                "developer": { "currency": "usd", "amount": "0.50", "amountUSD": "0.50" }
            },
            "exchangeRate": 1.0,
            "status": "processing",
            "createdAt": "2026-01-27T15:30:00.000Z",
            "updatedAt": "2026-01-27T16:00:00.000Z",
            "quoteId": "355e0a5c-76a5-4d13-bcee-f2ad39abe710",
            "expiresAt": "2026-01-28T15:30:00.000Z"
        }
    }
}
```

| Field                              | Type                | Description                                                                                                                                                                                                                                    |
| ---------------------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                               | `string`            | The transaction ID                                                                                                                                                                                                                             |
| `type`                             | `string`            | Always `transfer` for this webhook                                                                                                                                                                                                             |
| `transfer.userId`                  | `string` (optional) | The user ID for consumer accounts                                                                                                                                                                                                              |
| `transfer.companyId`               | `string` (optional) | The company ID for corporate accounts                                                                                                                                                                                                          |
| `transfer.source.amount`           | `string`            | Source amount as a decimal string (for example, `"100.00"`)                                                                                                                                                                                    |
| `transfer.source.currency`         | `string`            | Source currency code                                                                                                                                                                                                                           |
| `transfer.source.rail`             | `string`            | Source rail (for example, `onchain`, `wire`)                                                                                                                                                                                                   |
| `transfer.source.referenceId`      | `string` (optional) | Source reference ID                                                                                                                                                                                                                            |
| `transfer.source.address`          | `object` (optional) | Source address (see [address types](#address-types))                                                                                                                                                                                           |
| `transfer.destination.amount`      | `string` (optional) | Destination amount as a decimal string                                                                                                                                                                                                         |
| `transfer.destination.currency`    | `string`            | Destination currency code                                                                                                                                                                                                                      |
| `transfer.destination.rail`        | `string`            | Destination rail                                                                                                                                                                                                                               |
| `transfer.destination.referenceId` | `string` (optional) | Destination reference ID                                                                                                                                                                                                                       |
| `transfer.destination.address`     | `object` (optional) | Destination address (see [address types](#address-types))                                                                                                                                                                                      |
| `transfer.depositAddress`          | `object` (optional) | Deposit address for the transfer (see [deposit address types](#deposit-address-types))                                                                                                                                                         |
| `transfer.fees.rain.currency`      | `string`            | Currency of Rain's fee                                                                                                                                                                                                                         |
| `transfer.fees.rain.amount`        | `string`            | Rain's fee amount as a decimal string                                                                                                                                                                                                          |
| `transfer.fees.rain.amountUSD`     | `string`            | Rain's fee amount in USD as a decimal string                                                                                                                                                                                                   |
| `transfer.fees.sender`             | `object` (optional) | [Sender fee](/docs/sender-fees) you configured, with the same `currency`, `amount`, and `amountUSD` shape. Present on transfers with a sender fee.                                                                                             |
| `transfer.fees.developer`          | `object` (optional) | Deprecated alias of `fees.sender`; read `sender` instead. Same `currency`, `amount`, and `amountUSD` shape.                                                                                                                                    |
| `transfer.exchangeRate`            | `number` (optional) | Exchange rate applied                                                                                                                                                                                                                          |
| `transfer.status`                  | `string`            | Transfer status. Never `settled`: a separate `transactionTransfer.completed` webhook covers that outcome. One of `pending`, `awaiting_transfer`, `processing`, `pending_review`, `failed`, `cancelled`, `expired`, or `refunded`.              |
| `transfer.createdAt`               | `string`            | ISO 8601 timestamp of creation                                                                                                                                                                                                                 |
| `transfer.updatedAt`               | `string`            | ISO 8601 timestamp of last update                                                                                                                                                                                                              |
| `transfer.quoteId`                 | `string`            | The quote ID this transfer was created from                                                                                                                                                                                                    |
| `transfer.expiresAt`               | `string`            | ISO 8601 timestamp of when the transfer expires                                                                                                                                                                                                |
| `transfer.refundReason`            | `string` (optional) | Why the transfer was refunded: `limit_exceeded`, `invalid_destination`, `returned_by_bank`, `expired`, `amount_mismatch`, or `other`. Present only on refunded transfers, and some refunds carry no reason. Requires version `1.1.0` or later. |

<Info>
  The `updated` webhook fires for in-flight progress (`processing`) and non-success terminals (`failed`, `cancelled`, `expired`, `refunded`).
</Info>

## `transactionTransfer.completed`

Rain sends this webhook when a transfer settles successfully at its destination.

### `transfer`

Rain sends the `transfer` webhook when a transfer settles at the destination.

```json Payload theme={null}
{
    "resource": "transactionTransfer",
    "action": "completed",
    "version": "1.0.0",
    "body": {
        "id": "txn_abc123",
        "type": "transfer",
        "transfer": {
            "companyId": "cmp_456abc",
            "source": {
                "amount": "1000.00",
                "currency": "usdc",
                "rail": "onchain",
                "referenceId": "ref_123",
                "address": {
                    "type": "onchain",
                    "address": "0x1234567890abcdef1234567890abcdef12345678"
                }
            },
            "destination": {
                "amount": "998.50",
                "currency": "usd",
                "rail": "wire",
                "referenceId": "ref_456",
                "address": {
                    "type": "paymentAccount",
                    "id": "pa_456def"
                }
            },
            "depositAddress": {
                "type": "fiat",
                "beneficiaryName": "Rain Financial Inc.",
                "beneficiaryAddress": "123 Main St, New York, NY",
                "beneficiaryBankName": "Example Bank",
                "beneficiaryBankAddress": "456 Bank Ave, New York, NY",
                "accountNumber": "1234567890",
                "routingNumber": "021000021"
            },
            "fees": {
                "rain": { "currency": "usd", "amount": "1.00", "amountUSD": "1.00" },
                "developer": { "currency": "usd", "amount": "0.50", "amountUSD": "0.50" }
            },
            "exchangeRate": 1.0,
            "status": "settled",
            "createdAt": "2026-01-27T15:30:00.000Z",
            "updatedAt": "2026-01-27T16:45:00.000Z",
            "quoteId": "355e0a5c-76a5-4d13-bcee-f2ad39abe710",
            "expiresAt": "2026-01-28T15:30:00.000Z"
        }
    }
}
```

| Field                              | Type                | Description                                                                                                                                                                                                                                    |
| ---------------------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                               | `string`            | The transaction ID                                                                                                                                                                                                                             |
| `type`                             | `string`            | Always `transfer` for this webhook                                                                                                                                                                                                             |
| `transfer.userId`                  | `string` (optional) | The user ID for consumer accounts                                                                                                                                                                                                              |
| `transfer.companyId`               | `string` (optional) | The company ID for corporate accounts                                                                                                                                                                                                          |
| `transfer.source.amount`           | `string`            | Source amount as a decimal string (for example, `"100.00"`)                                                                                                                                                                                    |
| `transfer.source.currency`         | `string`            | Source currency code                                                                                                                                                                                                                           |
| `transfer.source.rail`             | `string`            | Source rail (for example, `onchain`, `wire`)                                                                                                                                                                                                   |
| `transfer.source.referenceId`      | `string` (optional) | Source reference ID                                                                                                                                                                                                                            |
| `transfer.source.address`          | `object` (optional) | Source address (see [address types](#address-types))                                                                                                                                                                                           |
| `transfer.destination.amount`      | `string` (optional) | Destination amount as a decimal string                                                                                                                                                                                                         |
| `transfer.destination.currency`    | `string`            | Destination currency code                                                                                                                                                                                                                      |
| `transfer.destination.rail`        | `string`            | Destination rail                                                                                                                                                                                                                               |
| `transfer.destination.referenceId` | `string` (optional) | Destination reference ID                                                                                                                                                                                                                       |
| `transfer.destination.address`     | `object` (optional) | Destination address (see [address types](#address-types))                                                                                                                                                                                      |
| `transfer.depositAddress`          | `object` (optional) | Deposit address for the transfer (see [deposit address types](#deposit-address-types))                                                                                                                                                         |
| `transfer.fees.rain.currency`      | `string`            | Currency of Rain's fee                                                                                                                                                                                                                         |
| `transfer.fees.rain.amount`        | `string`            | Rain's fee amount as a decimal string                                                                                                                                                                                                          |
| `transfer.fees.rain.amountUSD`     | `string`            | Rain's fee amount in USD as a decimal string                                                                                                                                                                                                   |
| `transfer.fees.sender`             | `object` (optional) | [Sender fee](/docs/sender-fees) you configured, with the same `currency`, `amount`, and `amountUSD` shape. Present on transfers with a sender fee.                                                                                             |
| `transfer.fees.developer`          | `object` (optional) | Deprecated alias of `fees.sender`; read `sender` instead. Same `currency`, `amount`, and `amountUSD` shape.                                                                                                                                    |
| `transfer.exchangeRate`            | `number` (optional) | Exchange rate applied                                                                                                                                                                                                                          |
| `transfer.status`                  | `string`            | Transfer status. Always `settled` for this webhook.                                                                                                                                                                                            |
| `transfer.createdAt`               | `string`            | ISO 8601 timestamp of creation                                                                                                                                                                                                                 |
| `transfer.updatedAt`               | `string`            | ISO 8601 timestamp of last update                                                                                                                                                                                                              |
| `transfer.quoteId`                 | `string`            | The quote ID this transfer was created from                                                                                                                                                                                                    |
| `transfer.expiresAt`               | `string`            | ISO 8601 timestamp of when the transfer expires                                                                                                                                                                                                |
| `transfer.refundReason`            | `string` (optional) | Why the transfer was refunded: `limit_exceeded`, `invalid_destination`, `returned_by_bank`, `expired`, `amount_mismatch`, or `other`. Present only on refunded transfers, and some refunds carry no reason. Requires version `1.1.0` or later. |

## Transfer object reference

The nested address fields and the `status` values used in the `transfer` object are detailed below.

### Address types

The `source.address` and `destination.address` fields can each take one of the following shapes.

An onchain address contains these fields:

| Field     | Type     | Description      |
| --------- | -------- | ---------------- |
| `type`    | `string` | Always `onchain` |
| `address` | `string` | Wallet address   |

A payment account address contains these fields:

| Field  | Type     | Description             |
| ------ | -------- | ----------------------- |
| `type` | `string` | Always `paymentAccount` |
| `id`   | `string` | Payment account ID      |

### Deposit address types

The `depositAddress` field can take one of the following shapes.

A fiat deposit address contains these fields:

| Field                    | Type                | Description              |
| ------------------------ | ------------------- | ------------------------ |
| `type`                   | `string`            | Always `fiat`            |
| `beneficiaryName`        | `string`            | Beneficiary name         |
| `beneficiaryAddress`     | `string`            | Beneficiary address      |
| `beneficiaryBankName`    | `string`            | Bank name                |
| `beneficiaryBankAddress` | `string`            | Bank address             |
| `accountNumber`          | `string`            | Account number           |
| `routingNumber`          | `string`            | Routing number           |
| `transferMessage`        | `string` (optional) | Transfer message or memo |

An onchain deposit address contains these fields:

| Field     | Type     | Description      |
| --------- | -------- | ---------------- |
| `type`    | `string` | Always `onchain` |
| `address` | `string` | Wallet address   |

### Transfer status values

The `status` field reflects where the transfer is in its lifecycle:

| Status              | Description                                                |
| ------------------- | ---------------------------------------------------------- |
| `pending`           | Transfer has been initiated                                |
| `awaiting_transfer` | Waiting for the incoming funds for the transfer            |
| `processing`        | Transfer is being processed                                |
| `pending_review`    | Transfer is held for review before it continues processing |
| `settled`           | Transfer has been completed successfully                   |
| `failed`            | Transfer has failed                                        |
| `cancelled`         | Transfer was cancelled                                     |
| `expired`           | Transfer expired before completion                         |
| `refunded`          | Transfer was refunded                                      |

## Fund movements

The spend `transaction.created`, `transaction.updated`, and
`transaction.completed` webhooks can include a `fundMovements` array that
describes the on-chain movements backing the card transaction, such as the
authorization pull that reserved funds on-chain, ordered oldest first. You
receive this field only if your tenant is opted in to the webhook version that
added it (`transaction.created` `1.3.0`, `transaction.updated` `1.2.0`,
`transaction.completed` `1.4.0`). Earlier versions never include it, and the
array is empty when no on-chain movements back the transaction.

Each entry in `fundMovements` has the following shape:

| Field         | Type     | Description                                                                                                                                                                                       |
| ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `hash`        | `string` | The on-chain transaction hash for this movement.                                                                                                                                                  |
| `chainId`     | `string` | The chain identifier where the movement settled, as a hex string (for example, `0x2105` for Base). `collateral.chainId` and `payment.chainId` elsewhere on this page are decimal numbers instead. |
| `kind`        | `string` | The type of fund movement. See the values below.                                                                                                                                                  |
| `direction`   | `string` | The direction of the movement: `debit` (funds pulled) or `credit` (funds returned, as on a `reversal`).                                                                                           |
| `amountCents` | `number` | The amount moved, in cents.                                                                                                                                                                       |
| `occurredAt`  | `string` | ISO 8601 timestamp of when the movement occurred on-chain.                                                                                                                                        |
| `currency`    | `string` | The currency of the movement. Requires `transaction.created` version `1.4.0` or `transaction.completed` version `1.5.0`; `transaction.updated` entries don't carry it.                            |

The `kind` field can take these values:

| Value              | Description                                                     |
| ------------------ | --------------------------------------------------------------- |
| `auth`             | Initial authorization pull.                                     |
| `incremental_auth` | Additional pull for an incremental authorization.               |
| `force_post`       | Pull backing a force-posted settlement.                         |
| `over_capture`     | Pull covering a settlement that exceeded the authorized amount. |
| `sweep`            | Pull that sweeps remaining funds for the transaction.           |
| `reversal`         | Funds returned on-chain when an authorization is reversed.      |

## What's next

<Columns cols={2}>
  <Card title="Sample webhooks" icon="code" href="/docs/sample-webhooks">
    See worked examples of a spend moving through these events end to end.
  </Card>

  <Card title="Decline reasons" icon="circle-exclamation" href="/docs/decline-reasons">
    Look up what a `declinedReason` value means and what to do about it.
  </Card>
</Columns>
