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

# B2B OTC Withdrawals

> Draft, quote, submit, officer review, execute, and settlement for crypto-to-fiat OTC withdrawals.

## Overview

Merchants sell stablecoins (USDT/USDC) for fiat through a **draft → quote → submit** wizard, or the legacy one-shot **`POST /api/v1/auth/otc/withdrawals`** (creates **`pending`** immediately). Ops (**admin** or **otc\_officer**) approve, execute on-chain debit to treasury, then pay fiat (bank manual or Mobile Money B2C).

Status flow: **`draft`** → **`priced`** → **`pending`** → **`approved`** → **`processing`** → **`completed`** (or **`rejected`**).

## Pricing (OTC-Scoped)

Create admin **`pricing_profiles`** and **`fx_rate_quotes`** with **`flow_type`: `b2b`** and **`otc_type`: `withdrawal`** on both rows.

Use **`POST /api/v1/auth/pricing/resolve-otc`** with **`amount_in_type`: `crypto`** (merchant sells crypto):

```json theme={null}
{
  "flow_type": "b2b",
  "otc_type": "withdrawal",
  "network": "tron",
  "asset": "USDT",
  "fiat_currency": "KES",
  "amount_in": "100",
  "amount_in_type": "crypto"
}
```

Copy **`pricing_profile_id`** and **`fx_rate_quote_id`** into **`PATCH /api/v1/auth/otc/withdrawals/{id}/quote`**, or use treasury-negotiated FX (below).

## Treasury-Negotiated FX (Withdrawals)

Merchants **sell crypto** (USDT/USDC) for a treasury-agreed fiat payout. Same reference table as deposits: **`otc_negotiated_fx_references`**.

**Prerequisite:** active **b2b** **`pricing_profiles`** row with **`otc_type: withdrawal`** matching asset, fiat, and network.

### Treasury Flow

1. **`POST /api/v1/auth/otc/negotiated-fx/references`** with **`otc_type: "withdrawal"`**, merchant, **`agreed_transaction_date`** (today or tomorrow in the reference timezone), asset, fiat, optional **`timezone`** or **`source_country`**, amounts, and rates.
2. Email notification (when **`EMAIL_ENABLED=true`**) CTA: *OTC Withdrawals → Enter FX Reference*.
3. Share **`reference_code`** with the merchant.

### Merchant Flow

1. **`POST .../withdrawals/draft`** with **`method`**, **`fiat_currency`**, **`from_wallet_id`**, and payout fields (Mobile Money phone or bank details).
2. **`PATCH .../withdrawals/{id}/quote`** with `{ "negotiated_fx_reference": "NFX-..." }` only (`reference_code` alias accepted). Do **not** send standard pricing fields on this path.
3. API debits **gross crypto** from the agreed terms, sets **net fiat payout** after fees, marks reference **consumed**, moves **draft → priced**.
4. **`POST .../submit`** → officer approve → execute (on-chain debit) → Mobile Money B2C or manual bank payout.

For Kenya Mobile Money: **`method: mpesa`**, **`fiat_currency: KES`**, timezone **`Africa/Nairobi`** (or **`source_country: KEN`**). Net fiat payout must be **≤ 500,000 KES**.

## Mobile Money Limit

KES Mobile Money withdrawals are capped at **500,000** per request (draft, quote, submit, and legacy create).

## Data Model

| Concern                   | Table                                                       |
| ------------------------- | ----------------------------------------------------------- |
| Withdrawal lifecycle      | **`otc_withdrawals`**                                       |
| Treasury-negotiated FX    | **`otc_negotiated_fx_references`** (`otc_type: withdrawal`) |
| Negotiated FX email audit | **`otc_negotiated_fx_notifications`**                       |
| Commercial pricing        | **`pricing_profiles`**                                      |
| FX snapshot               | **`fx_rate_quotes`**                                        |
| Source wallet             | **`wallets`** (**`from_wallet_id`**)                        |
| On-chain debit            | **`transfers`**                                             |
| Mobile Money payout       | **`otc_mpesa_payouts`**                                     |
| Audit trail               | **`otc_withdrawal_audit`**                                  |

## Wizard Endpoints

| Step       | Method  | Path                                           |
| ---------- | ------- | ---------------------------------------------- |
| 1. Draft   | `POST`  | `/api/v1/auth/otc/withdrawals/draft`           |
| 2. Quote   | `PATCH` | `/api/v1/auth/otc/withdrawals/{id}/quote`      |
| 3. Submit  | `POST`  | `/api/v1/auth/otc/withdrawals/{id}/submit`     |
| Settlement | `GET`   | `/api/v1/auth/otc/withdrawals/{id}/settlement` |
| Audit      | `GET`   | `/api/v1/auth/otc/withdrawals/{id}/audit`      |

Ops queues: **`GET .../queue/pending`**, **`GET .../queue/approved`**. Approve **`POST .../approve`**, reject **`POST .../reject`**, execute **`POST .../execute`** (**admin**, **otc\_officer**, or **treasury**). Bank fiat payout: **`POST .../record-bank-payout`** with `bank_payout_reference` after manual transfer.

**Maker-checker:** same `OTC_OFFICER_MAX_USD` limit applies to approve/execute for **otc\_officer**. **ADMIN** and **treasury** are unlimited.
