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

# Deposits

> A detailed explanation concerning what happens end-to-end when crypto lands on a Breet-generated wallet address.

A **deposit** happens when crypto is sent to a wallet address you generated via the API. Breet detects the transaction on-chain, waits for confirmations, runs checks, converts the value to FIAT, and credits your Breet wallet — or pays it out to a bank if you've enabled [auto-settlement](/auto-settlement).

Every deposit, successful or not, fires a [webhook](/webhooks) so you can react in real time.

<Tip>
  You don't need real crypto to integrate. In the `development` environment, you can mock deposits to any of your addresses and exercise the full lifecycle — webhooks, confirmations, auto-settlement, everything — without sending real funds. See [Testing](/testing) for the step-by-step.
</Tip>

Let's dig in further.

## Deposit states

| State       | What it means                                                                                  |
| ----------- | ---------------------------------------------------------------------------------------------- |
| `pending`   | Detected on-chain, waiting for confirmations. Nothing has been credited.                       |
| `completed` | Fully confirmed, checks passed, wallet credited (and settled if auto-settlement is on).        |
| `flagged`   | Confirmed on-chain but below the asset's minimum deposit amount. Funds are held, not credited. |

Each state change fires `trade.pending`, `trade.completed`, or `trade.flagged`.

## Happy path

<Steps>
  <Step title="You generate a deposit address">
    Call [`POST /trades/sell/assets/{id}/generate-address`](/api-reference/crypto-wallet/generate-wallet-address) once per asset per user. Addresses are permanent and reusable — no need to generate a fresh one per deposit.
  </Step>

  <Step title="Your customer sends crypto">
    Any wallet or exchange, any amount. Breet has no control over this step.
  </Step>

  <Step title="Breet detects the transaction">
    When the transaction appears on-chain, Breet creates a deposit record and fires `trade.pending` with `confirmations: 0`, the `txHash`, and the amount.
  </Step>

  <Step title="Breet waits for confirmations">
    Confirmations required are configured per asset — don't hardcode them. Treat `trade.completed` or `trade.flagged` as your source of truth. `trade.pending` may fire multiple times as `confirmations` increments.
  </Step>

  <Step title="Breet checks the amount">
    On the final confirmation, Breet checks that the deposit's USD value meets the asset's minimum ([see thresholds](/supported-assets) or call [`GET /trades/assets`](/api-reference/assets/fetch-deposit-assets)).

    Meets the minimum → `completed`. Below the minimum → `flagged`.
  </Step>

  <Step title="Breet credits your wallet">
    On `completed`, Breet converts the USD value to your receive currency (USD, NGN, or GHS), deducts the platform fee (`feeAmountInUsd`), and credits your balance. `trade.completed` fires with the final amounts.

    If auto-settlement is enabled on the address, Breet also pays the net amount to the linked bank account. See [Auto-settlement](/auto-settlement) for the explanation.
  </Step>
</Steps>

## Webhook sequence, by scenario

| Scenario                 | Events (same `id`)                                                     |
| ------------------------ | ---------------------------------------------------------------------- |
| Clean deposit            | `trade.pending` → `trade.completed`                                    |
| Slow confirmations       | `trade.pending` (×N as `confirmations` increments) → `trade.completed` |
| Below minimum            | `trade.pending` → `trade.flagged`                                      |
| Flagged → later resolved | `trade.flagged` → `trade.completed`                                    |

<Tip>
  Use `id` + `event` as your idempotency key. Breet retries non-2xx deliveries up to 7 times — see [Webhooks](/webhooks#webhook-retries).
</Tip>

## What happens when a deposit is flagged

A flagged deposit is held, not lost. Example: your customer sends \$3 of USDT on Tron, minimum is \$20. The deposit sits in `flagged` until one of two things happens:

1. **Customer tops up.** Any later deposit to the **same address** in the **same asset** combines with outstanding flagged deposits at that address. The moment the combined USD total crosses the minimum, every flagged deposit flips to `completed` in one batch — one credit, one `trade.completed` per deposit. No fee applied.

2. **You pay a resolution fee from your dashboard.** Log in to [partners.breet.io](https://partners.breet.io), open the flagged transaction, click **Pay Resolution Fee**, and confirm. Breet deducts the resolution fee from the USD value of the crypto that was actually received, credits the remainder to your wallet immediately, and fires `trade.completed` with the `flagFeeUSD` field populated so your system knows a fee was applied.

## Edge cases

### Wrong asset

If a customer sends a **different asset** to one of your addresses (e.g. they send ETH to a USDT address), recovery is **automatic** — no support ticket needed. This applies only if the received asset is one of our [supported assets](/supported-assets).

What happens behind the scenes:

1. We detect the asset mismatch.
2. A new address is generated on your integration for the asset that actually arrived. The original wallet's bank account and auto-settlement configurations are carried over.
3. The deposit processes as a normal trade on the new wallet.

**Webhooks you'll receive, in order:**

* [`trade.address.created`](https://docs.breet.io/webhooks#address-creation-webhook) — new address payload with `id`, `address`, `asset`, `label`, and `createdAt`.
* An email from us confirming the mismatch and recovery. No action needed on your end.
* `trade.pending` → `trade.completed` — standard trade lifecycle on the new wallet. The `trade.pending` payload includes `isWrongAssetDeposit: true` so you can identify this as a wrong-asset recovery.
* If auto-settlement was **on**: `withdrawal.pending` → `withdrawal.processing` → `withdrawal.completed`. Funds settle to the bank account from the original wallet.
* If auto-settlement was **off**: funds credit your dashboard balance. Resolve with your user from there as you normally would.

### USD value and timing

`amountInUSD` is recalculated on each webhook, not locked at detection. The value on `trade.completed` is authoritative — use it for accounting. Local-currency conversion uses the `rate` at completion time.

### Chain reorganisations

Rare on supported networks. If a pending deposit is orphaned before it confirms, the deposit moves to a non-credited terminal state — always before `trade.completed` could fire.

## Fetching deposits via the API

Rather than relying only on webhooks, you can inspect deposits directly:

| Purpose                    | Endpoint                                                                               |
| -------------------------- | -------------------------------------------------------------------------------------- |
| List deposits              | [`GET /trades/transactions`](/api-reference/transactions/fetch-transactions)           |
| Fetch one by ID            | [`GET /trades/transactions/{id}`](/api-reference/transactions/fetch-transaction-by-id) |
| List your wallet addresses | [`GET /trades/wallets`](/api-reference/crypto-wallet/fetch-wallet-addresses)           |

<Tip>
  On every webhook, fetch the deposit by `id` before updating your system of record. Combined with [IP and secret verification](/webhooks#webhook-verification), this is defence in depth.
</Tip>

## FAQ

<AccordionGroup>
  <Accordion title="How long can a deposit stay pending?">
    Seconds/Minutes on Solana/Tron/TON; up to an hour on slow chains. If a deposit is pending for more than 6 hours, contact support with the `txHash`.
  </Accordion>

  <Accordion title="Should I use one address for multiple customers?">
    No. Generate a separate address per customer (or per order) and pass their ID in the `label` field. When a deposit webhook fires, `destinationAddress` and `destinationDescription` (the label) tell you exactly who paid.

    Addresses are permanent and reusable, so you generate a customer's address once, store it, and reuse it for all their future deposits.
  </Accordion>

  <Accordion title="Does Breet charge a network/gas fee on deposits?">
    No. Your customer pays their own on-chain fee. Breet's only charge on a deposit is the platform fee (`feeAmountInUsd`).
  </Accordion>

  <Accordion title="What's the difference between `feeAmountInUsd` and `flagFeeUSD`?">
    `feeAmountInUsd` is the platform fee on a normal completed deposit. `flagFeeUSD` is the resolution fee applied when you pay to release a flagged below-minimum deposit from your dashboard. On the happy path, `flagFeeUSD` is `0`.
  </Accordion>
</AccordionGroup>

## Next steps

* Move funds out of your wallet → [Withdrawals](/withdrawals)
* Set up webhook handling → [Webhooks](/webhooks)
* Settle deposits automatically → [Auto-settlement](/auto-settlement)
* See supported assets and minimums → [Supported assets](/supported-assets)
* Simulate a deposit on testnet → [Testing](/testing)
