Overview
Merchants sell stablecoins (USDT/USDC) for fiat through a draft → quote → submit wizard, or the legacy one-shotPOST /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 adminpricing_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):
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
POST /api/v1/auth/otc/negotiated-fx/referenceswithotc_type: "withdrawal", merchant,agreed_transaction_date(today or tomorrow in the reference timezone), asset, fiat, optionaltimezoneorsource_country, amounts, and rates.- Email notification (when
EMAIL_ENABLED=true) CTA: OTC Withdrawals → Enter FX Reference. - Share
reference_codewith the merchant.
Merchant Flow
POST .../withdrawals/draftwithmethod,fiat_currency,from_wallet_id, and payout fields (Mobile Money phone or bank details).PATCH .../withdrawals/{id}/quotewith{ "negotiated_fx_reference": "NFX-..." }only (reference_codealias accepted). Do not send standard pricing fields on this path.- API debits gross crypto from the agreed terms, sets net fiat payout after fees, marks reference consumed, moves draft → priced.
POST .../submit→ officer approve → execute (on-chain debit) → Mobile Money B2C or manual bank payout.
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
Wizard Endpoints
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.