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

# Webhook Structure

## Payload Structure

Every event contains a `data` object with the transaction snapshot at the moment of the event. The payload structure is the same for all event types, but field values differ depending on the transaction type and lifecycle stage.

```json theme={null}
{
  id: "uuid",                          // Transaction ID
  externalId: "string",                // Integrator's external order identifier
  type: "Buy" | "Sale",                // "Buy" = withdrawal, "Sale" = acquiring
  status: "TransactionStatus",         // Current status

  // Currency & pair
  pair: "string",                      // Trading pair: "USDT/TRX" (withdrawal) or "BTC/USDT" (acquiring)
  currency: "string",                  // Target currency
  network: "string",                   // Blockchain network: "TRC20", "ERC20", "Bitcoin", etc.

  // Amounts (see "Amount Fields Explained" section below)
  requestedAmount: "string",           // Net amount user receives (withdrawal) or expects to deposit (acquiring)
  expectedAmount: "string",            // Total incl. network fee (withdrawal) or same as requestedAmount (acquiring)
  amount: "string | null",             // Cumulative actual amount. null until processed.
  usdtTotal: "string | null",          // USDT reserved with hold (withdrawal) or cumulative USDT credited (acquiring)
  exchangeRate: "string | null",       // Preview rate at creation, actual rate after conversion
  dealFee: "string | null",            // Commission/fee charged on the transaction

  // Received deposit info (acquiring `deposit_received` event only)
  receivedCurrency: "string | null",   // Actual deposited cryptocurrency (this deposit)
  receivedNetwork: "string | null",    // Network of the received deposit
  receivedAmount: "string | null",     // Individual deposit amount in receivedCurrency (NOT cumulative)

  // Blockchain
  address: "string",                   // Destination (withdrawal) or deposit address (acquiring)
  hash: "string | null",               // Blockchain transaction hash, empty string until available
  memo: "string | null",               // Memo/tag for networks that require it (XRP, XLM, etc.)

  // Metadata
  merchantId: "uuid",                  // Merchant identifier
  cancelReason: "string | null",       // Reason for cancellation (only on failure/cancel events)
  createdAt: "ISO 8601",               // Transaction creation time
  updatedAt: "ISO 8601",               // Last update time
  completedAt: "ISO 8601 | null"       // Completion time, null until finalized
}
```

### Amount Fields Explained

There are four amount-related fields and they serve different purposes depending on the transaction type.

#### Withdrawal (Buy)

| Field             | Meaning                                                            | Example       |
| ----------------- | ------------------------------------------------------------------ | ------------- |
| `requestedAmount` | Net amount the user will receive on blockchain                     | `"25"` TRX    |
| `expectedAmount`  | Total amount including network fee: `requestedAmount + networkFee` | `"25.5"` TRX  |
| `amount`          | Actual amount sent (reported after blockchain send)                | `"25"` TRX    |
| `usdtTotal`       | USDT reserved from balance including 1.25% hold buffer             | `"7.52"` USDT |

If the integrator passes `includeFeeInAmount: true`, the calculation is reversed: `expectedAmount` = original amount, `requestedAmount` = original amount - networkFee. The relationship is always: `expectedAmount = requestedAmount + networkFee`.

`usdtTotal` is calculated as: convert `expectedAmount` to USDT at preview rate, then add 1.25% hold buffer. This is the total USDT deducted from the merchant's balance. After conversion, excess hold is returned.

Example:

```
You requests: withdraw 25 TRX
  requestedAmount = "25"       ← what the user receives
  expectedAmount  = "25.5"     ← 25 + 0.5 network fee
  exchangeRate    = "0.2971"   ← preview USDT/TRX rate
  usdtTotal       = "7.68"    ← (25.5 × 0.2971) × 1.0125 hold buffer

After blockchain send:
  amount          = "25"       ← actual sent
```

#### Acquiring (Sale)

| Field             | Meaning                                                                      | Example        |
| ----------------- | ---------------------------------------------------------------------------- | -------------- |
| `requestedAmount` | Amount the integrator expects to receive as deposit                          | `"0.001"` BTC  |
| `expectedAmount`  | Same as `requestedAmount`                                                    | `"0.001"` BTC  |
| `amount`          | Cumulative actual deposit total across all partial deposits                  | `"0.0012"` BTC |
| `receivedAmount`  | Individual deposit amount in `receivedCurrency` (only on `deposit_received`) | `"0.0005"` BTC |
| `usdtTotal`       | Cumulative USDT credited to the merchant's balance (after fees)              | `"45.30"` USDT |

For acquiring, `requestedAmount` and `expectedAmount` are always identical. The `amount` field shows the actual total received. By comparing `amount` to `expectedAmount`, the system determines the transaction status: `Paid` (equal), `Overpaid` (more), `Underpaid` (less).

Example:

```
You creates order: deposit 0.001 BTC
  requestedAmount = "0.001"    ← expected deposit
  expectedAmount  = "0.001"    ← same value
  amount          = null       ← no deposit yet
  usdtTotal       = null

After deposit confirmed:
  amount          = "0.0012"   ← actual received (overpaid)
  usdtTotal       = "45.30"   ← USDT credited after fees
  exchangeRate    = "37750"    ← BTC/USDT rate used
  status          = "Overpaid"
```

Summary

| Field             | Withdrawal                        | Acquiring                  |
| ----------------- | --------------------------------- | -------------------------- |
| `requestedAmount` | Net amount to receive (excl. fee) | Expected deposit amount    |
| `expectedAmount`  | Gross amount (incl. network fee)  | Same as `requestedAmount`  |
| `amount`          | Sent amount                       | Cumulative actual deposits |
| `usdtTotal`       | USDT reserved (with 1.25% hold)   | Cumulative USDT credited   |

## Status Values

| Status                 | Used in    | Description                                           |
| ---------------------- | ---------- | ----------------------------------------------------- |
| `Queued`               | Withdrawal | Queued for processing                                 |
| `New`                  | Acquiring  | Order created, awaiting deposit                       |
| `Waiting`              | Acquiring  | Blockchain confirmation in progress                   |
| `Paid`                 | Acquiring  | Deposit matches expected amount                       |
| `Overpaid`             | Acquiring  | Deposit exceeds expected amount                       |
| `Underpaid`            | Acquiring  | Deposit less than expected amount                     |
| `Canceled`             | Both       | Transaction canceled / declined / failed              |
| `CurrencyMismatch`     | Acquiring  | Wrong cryptocurrency was deposited                    |
| `CanceledButPaid`      | Acquiring  | Order expired/declined but exact deposit was received |
| `CanceledButOverpaid`  | Acquiring  | Order expired/declined but overpayment was received   |
| `CanceledButUnderpaid` | Acquiring  | Order expired/declined but underpayment was received  |

## Currency Logic

The `currency` field represents what was expected, not what was actually received:

* Withdrawal: the target cryptocurrency being purchased (e.g. `"TRX"`, `"BTC"`)
* Acquiring: the expected deposit cryptocurrency from the order configuration (e.g. `"BTC"`)

The actually received cryptocurrency is reported in `receivedCurrency` (see below).

### Received Fields (`receivedCurrency`, `receivedNetwork`, `receivedAmount`)

These three fields represent what was actually deposited on the blockchain for a specific deposit. They are only populated on the `deposit_received` event and always `null` for all other events.

* `receivedAmount` contains the individual deposit value from the specific webhook, NOT the cumulative total (use `amount` for cumulative)
* `receivedCurrency` is the cryptocurrency ticker of this specific deposit
* `receivedNetwork` is the blockchain network of the deposit

| Scenario                       | `receivedCurrency`   | `receivedNetwork` | `receivedAmount`          |
| ------------------------------ | -------------------- | ----------------- | ------------------------- |
| Withdrawal (any event)         | `null`               | `null`            | `null`                    |
| Acquiring — `deposit_received` | actual crypto ticker | deposit network   | individual deposit amount |
| Acquiring — all other events   | `null`               | `null`            | `null`                    |

### Per-Event Field Details

#### Withdrawal Events

| Field          | `created`      | `completed`     | `declined` | `failed`      | `canceled`      |
| -------------- | -------------- | --------------- | ---------- | ------------- | --------------- |
| `status`       | `Queued`       | final status    | `Canceled` | `Canceled`    | `Canceled`      |
| `amount`       | `null`         | final amount    | from DB    | from DB       | from DB         |
| `hash`         | `""`           | blockchain hash | hash       | may be `""`   | may be `""`     |
| `usdtTotal`    | reserve amount | final value     | from DB    | from DB       | from DB         |
| `exchangeRate` | preview rate   | actual rate     | from DB    | from DB       | from DB         |
| `dealFee`      | `"0"`          | calculated      | from DB    | from DB       | from DB         |
| `cancelReason` | `null`         | `null`          | reason     | error message | rollback reason |
| `completedAt`  | `null`         | timestamp       | `null`     | `null`        | `null`          |
| `received*`    | `null`         | `null`          | `null`     | `null`        | `null`          |

#### Acquiring Events

| Field              | `created`       | `confirmation_started` | `deposit_received`        | `completed` / `overpaid` / `underpaid` / `currency_mismatch` | `declined`           | `canceled`      |
| ------------------ | --------------- | ---------------------- | ------------------------- | ------------------------------------------------------------ | -------------------- | --------------- |
| `status`           | `New`           | `Waiting`              | varies                    | varies                                                       | varies               | `Canceled`      |
| `currency`         | expected crypto | expected crypto        | expected crypto           | expected crypto                                              | expected crypto      | expected crypto |
| `receivedCurrency` | `null`          | `null`                 | actual crypto             | `null`                                                       | `null`               | `null`          |
| `receivedNetwork`  | `null`          | `null`                 | deposit network           | `null`                                                       | `null`               | `null`          |
| `receivedAmount`   | `null`          | `null`                 | individual deposit amount | `null`                                                       | `null`               | `null`          |
| `amount`           | `null`          | `null`                 | cumulative                | cumulative                                                   | cumulative or `null` | `null`          |
| `hash`             | `""`            | blockchain hash        | hash                      | hash                                                         | hash                 | `""`            |
| `usdtTotal`        | `null`          | `null`                 | cumulative USDT           | cumulative USDT                                              | cumulative or `null` | `null`          |
| `exchangeRate`     | `null`          | `null`                 | weighted avg              | weighted avg                                                 | from DB              | `null`          |
| `dealFee`          | `null`          | `null`                 | calculated                | calculated                                                   | from DB              | `null`          |
| `completedAt`      | `null`          | `null`                 | if available              | if available                                                 | if available         | `null`          |
| `cancelReason`     | `null`          | `null`                 | `null`                    | `null`                                                       | `null`               | `null`          |

Notes:

* `deposit_received` is always emitted together with one of: `completed`, `overpaid`, `underpaid`, or `currency_mismatch`
* `declined` may or may not have deposit data depending on whether any deposits were received before the decline
* Acquiring amounts are cumulative across multiple deposits (each `was_final_exchange` webhook adds to the total)
* For `currency_mismatch`, `currency` shows what was expected and `receivedCurrency` shows what was actually sent
