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

> Follow a fiat deposit from bank receipt to on-chain settlement with webhooks

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 `provider_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.

Every deposit event shares the same envelope, with the stage-specific details under `data`:

<Expandable title="shared attributes" defaultOpen="true">
  <ResponseField name="type" type="string" required>
    Type of the webhook event.
  </ResponseField>

  <ResponseField name="provider_deposit_id" type="string">
    The deposit's ID in the provider's system, not a Privy ID. Stable across every event for the
    same deposit. Omitted on `deposit_failed` when the provider never assigned one.
  </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>
</Expandable>

<Tabs>
  <Tab title="Deposit started">
    <Expandable title="data attributes" defaultOpen="true">
      <ResponseField name="data.source" type="object" required>
        The fiat that was received.

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

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

          <ResponseField name="data.source.payment_rail" type="string">
            Rail the deposit arrived over, such as `ach_push`, `wire`, `sepa`, `fednow`, or
            `faster_payments`.
          </ResponseField>

          <ResponseField name="data.source.sender_name" type="string">
            Name of the originator, when the rail provides it.
          </ResponseField>
        </Expandable>
      </ResponseField>

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

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

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

  <Tab title="Deposit completed">
    The completed event carries the same `source` as `deposit_started`, and its `destination` adds the
    delivered crypto amount and the settlement transaction.

    <Expandable title="data attributes" defaultOpen="true">
      <ResponseField name="data.source" type="object" required>
        The fiat that was deposited, containing `amount`, `currency`, and optionally `payment_rail`
        and `sender_name`.
      </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.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",
      "provider_deposit_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "deposit_account_id": "da_xxxxx",
      "wallet_id": "dk3kud7kfo2jcnc5anoovdim",
      "deposit_type": "fiat",
      "provider": "bridge",
      "environment": "production",
      "data": {
        "source": {
          "amount": "1970.00",
          "currency": "usd",
          "payment_rail": "ach_push",
          "sender_name": "John Doe"
        },
        "destination": {
          "asset": "usdc",
          "chain": "tempo",
          "amount": "1968.40",
          "transaction_hash": "0xabc123..."
        },
        "created_at": "2026-08-03T14:32:00Z"
      }
    }
    ```
  </Tab>

  <Tab title="Deposit failed">
    <Expandable title="data attributes" defaultOpen="true">
      <ResponseField name="data.source" type="object" required>
        The fiat that was refunded, containing `amount`, `currency`, and optionally `payment_rail` and
        `sender_name`.
      </ResponseField>

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

      <ResponseField name="data.reason_code" type="string" required>
        Machine-readable failure code from the provider.
      </ResponseField>

      <ResponseField name="data.reason" type="string" required>
        Human-readable explanation of the failure.
      </ResponseField>

      <ResponseField name="data.refunded_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",
      "provider_deposit_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "deposit_account_id": "da_xxxxx",
      "wallet_id": "dk3kud7kfo2jcnc5anoovdim",
      "deposit_type": "fiat",
      "provider": "bridge",
      "environment": "production",
      "data": {
        "source": {
          "amount": "1970.00",
          "currency": "usd",
          "payment_rail": "ach_push",
          "sender_name": "John Doe"
        },
        "destination": {
          "asset": "usdc",
          "chain": "tempo"
        },
        "reason_code": "conversion_failed",
        "reason": "Unable to convert funds — refund initiated",
        "refunded_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>
