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

# Deposit lifecycle

A deposit moves through the provider asynchronously: fiat lands in the bank account, converts to crypto, then settles on-chain. Privy emits a webhook at each stage, keyed to a stable `deposit_id`.

| Event                                      | Fires when                                                                                 |
| ------------------------------------------ | ------------------------------------------------------------------------------------------ |
| `wallet.deposit_account.deposit_started`   | Privy can confirm receipt of the deposit in the account, and has initiated the conversion. |
| `wallet.deposit_account.deposit_completed` | Conversion finished and the crypto settled on-chain in the wallet.                         |
| `wallet.deposit_account.deposit_failed`    | Conversion failed and the fiat was refunded to the sender.                                 |

<Info>
  Webhooks can be tested at no cost in development environments. To enable webhooks in production,
  upgrade to the Enterprise plan in the Privy Dashboard.
</Info>

Privy also emits the existing [`wallet.funds_deposited`](/wallets/gas-and-asset-management/assets/balance-event-webhooks) event when the crypto lands in the wallet.

<Tabs>
  <Tab title="Deposit started">
    <Expandable title="wallet.deposit_account.deposit_started attributes" defaultOpen="true">
      <ResponseField name="type" type="'wallet.deposit_account.deposit_started'" required>
        Type of the webhook event.
      </ResponseField>

      <ResponseField name="deposit_id" type="string" required>
        ID of the deposit. Stable across every event for the same deposit.
      </ResponseField>

      <ResponseField name="deposit_account_id" type="string" required>
        ID of the deposit account that received the funds.
      </ResponseField>

      <ResponseField name="wallet_id" type="string" required>
        ID of the wallet the deposit is delivered to.
      </ResponseField>

      <ResponseField name="deposit_type" type="'fiat'" required>
        Type of the deposit.
      </ResponseField>

      <ResponseField name="provider" type="'bridge'" required>
        Provider that orchestrated the deposit.
      </ResponseField>

      <ResponseField name="environment" type="'production' | 'sandbox'" required>
        Provider environment the deposit account belongs to.
      </ResponseField>

      <ResponseField name="data" type="object" required>
        Details of the deposit.

        <Expandable title="properties" defaultOpen>
          <ResponseField name="data.amount" type="string" required>
            Fiat amount received, as a decimal string.
          </ResponseField>

          <ResponseField name="data.currency" type="'usd' | 'eur'" required>
            Currency of the fiat received.
          </ResponseField>

          <ResponseField name="data.destination" type="object" required>
            The `asset` and `chain` the deposit is being converted into.
          </ResponseField>

          <ResponseField name="data.source" type="object" required>
            Details of the originator, containing `sender_name` and `payment_rail`.
          </ResponseField>

          <ResponseField name="data.created_at" type="string" required>
            When the deposit was received, as an ISO 8601 timestamp.
          </ResponseField>
        </Expandable>
      </ResponseField>
    </Expandable>

    ```json theme={"system"}
    {
      "type": "wallet.deposit_account.deposit_started",
      "deposit_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "deposit_account_id": "da_xxxxx",
      "wallet_id": "dk3kud7kfo2jcnc5anoovdim",
      "deposit_type": "fiat",
      "provider": "bridge",
      "environment": "production",
      "data": {
        "amount": "1970.00",
        "currency": "usd",
        "destination": {
          "asset": "usdc",
          "chain": "tempo"
        },
        "source": {
          "sender_name": "John Doe",
          "payment_rail": "ach_push"
        },
        "created_at": "2026-08-03T14:30:00Z"
      }
    }
    ```
  </Tab>

  <Tab title="Deposit completed">
    The completed event carries the same fields as `deposit_started`, with the delivered crypto and the fees deducted during conversion.

    <Expandable title="wallet.deposit_account.deposit_completed data attributes" defaultOpen="true">
      <ResponseField name="data.amount" type="string" required>
        Fiat amount that was deposited, as a decimal string.
      </ResponseField>

      <ResponseField name="data.currency" type="'usd' | 'eur'" required>
        Currency of the fiat deposited.
      </ResponseField>

      <ResponseField name="data.destination" type="object" required>
        Settlement details of the delivered crypto.

        <Expandable title="properties" defaultOpen>
          <ResponseField name="data.destination.asset" type="string" required>
            Asset delivered to the wallet.
          </ResponseField>

          <ResponseField name="data.destination.chain" type="string" required>
            Chain the asset was delivered on.
          </ResponseField>

          <ResponseField name="data.destination.amount" type="string" required>
            Crypto amount delivered, after conversion and fees.
          </ResponseField>

          <ResponseField name="data.destination.transaction_hash" type="string" required>
            Hash of the on-chain settlement transaction.
          </ResponseField>
        </Expandable>
      </ResponseField>

      <ResponseField name="data.source" type="object" required>
        Details of the originator, containing `sender_name` and `payment_rail`.
      </ResponseField>

      <ResponseField name="data.fees" type="object" required>
        Fees deducted during conversion, containing `developer_fee`, `exchange_fee`, and `gas_fee`.
      </ResponseField>

      <ResponseField name="data.created_at" type="string" required>
        When the crypto was delivered, as an ISO 8601 timestamp.
      </ResponseField>
    </Expandable>

    ```json theme={"system"}
    {
      "type": "wallet.deposit_account.deposit_completed",
      "deposit_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "deposit_account_id": "da_xxxxx",
      "wallet_id": "dk3kud7kfo2jcnc5anoovdim",
      "deposit_type": "fiat",
      "provider": "bridge",
      "environment": "production",
      "data": {
        "amount": "1970.00",
        "currency": "usd",
        "destination": {
          "asset": "usdc",
          "chain": "tempo",
          "amount": "1968.40",
          "transaction_hash": "0xabc123..."
        },
        "source": {
          "sender_name": "John Doe",
          "payment_rail": "ach_push"
        },
        "fees": {
          "developer_fee": "1.00",
          "exchange_fee": "0.50",
          "gas_fee": "0.10"
        },
        "created_at": "2026-08-03T14:32:00Z"
      }
    }
    ```
  </Tab>

  <Tab title="Deposit failed">
    <Expandable title="wallet.deposit_account.deposit_failed data attributes" defaultOpen="true">
      <ResponseField name="data.amount" type="string" required>
        Fiat amount that was refunded, as a decimal string.
      </ResponseField>

      <ResponseField name="data.currency" type="'usd' | 'eur'" required>
        Currency of the refunded fiat.
      </ResponseField>

      <ResponseField name="data.destination" type="object" required>
        The `asset` and `chain` the deposit would have been delivered as.
      </ResponseField>

      <ResponseField name="data.source" type="object" required>
        Details of the originator, containing `sender_name` and `payment_rail`.
      </ResponseField>

      <ResponseField name="data.error" type="object" required>
        Why the deposit failed, containing a machine-readable `reason` and a human-readable `message`.
      </ResponseField>

      <ResponseField name="data.failed_at" type="string" required>
        When the refund settled, as an ISO 8601 timestamp.
      </ResponseField>

      <ResponseField name="data.created_at" type="string" required>
        When the failure was reported, as an ISO 8601 timestamp.
      </ResponseField>
    </Expandable>

    ```json theme={"system"}
    {
      "type": "wallet.deposit_account.deposit_failed",
      "deposit_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "deposit_account_id": "da_xxxxx",
      "wallet_id": "dk3kud7kfo2jcnc5anoovdim",
      "deposit_type": "fiat",
      "provider": "bridge",
      "environment": "production",
      "data": {
        "amount": "1970.00",
        "currency": "usd",
        "destination": {
          "asset": "usdc",
          "chain": "tempo"
        },
        "source": {
          "sender_name": "John Doe",
          "payment_rail": "ach_push"
        },
        "error": {
          "reason": "conversion_failed",
          "message": "Unable to convert funds — refund initiated"
        },
        "failed_at": "2026-08-03T14:35:00Z",
        "created_at": "2026-08-03T14:35:00Z"
      }
    }
    ```
  </Tab>
</Tabs>

## Next steps

<CardGroup cols={2}>
  <Card title="Handling webhook events" icon="webhook" href="/user-management/users/webhooks/handling-events">
    Configure an endpoint to receive Privy webhook events
  </Card>

  <Card title="Create a deposit account" icon="building-columns" href="/wallets/funding/fiat-deposits/create-deposit-account">
    Provision bank details for a wallet
  </Card>
</CardGroup>
