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

# Create Master Merchant (Vendor) With Default Wallets

> Creates a new **master merchant** (vendor user) and best-effort provisions default custodial wallets on **ethereum**, **tron**, and **solana**.

**Duplicate contact guard:** Returns **409** when **email** or **phone_number** is already registered. No user row and no wallets are created.

Wallet provisioning is **best-effort**: if one network fails (for example BitGo `hteth` quota), the API still creates wallets on the other networks and returns **`wallet_errors`** plus a **`warning`**. This applies only after the merchant user is created successfully.

- Role is always set to `vendor`
- `parent_vendor_id` is `null` for master merchants
- Default wallets (best-effort, one per network):
  - Ethereum wallet (`is_default=true`)
  - TRON wallet
  - Solana wallet (BitGo custody required)




## OpenAPI

````yaml /openapi.yaml post /api/v1/auth/merchants
openapi: 3.1.0
info:
  title: EmaalCoin API
  description: >
    EmaalCoin API reference. These APIs power cryptocurrency exchange between
    USDT and Fiat trading.


    - **On-Ramp**: Buy USDT with fiat (KES) via mobile money (STK Push for
    Kenya)

    - **Off-Ramp**: Sell USDT for KES with mobile money payout (Kenya)

    - **Ethereum, TRON, and Solana**: Multi-chain wallet support

    - **Merchant Offers**: Create and manage trading offers

    - **OTC Flows**: Bank and mobile money deposits/withdrawals for merchants

    - **Pricing engine**: FX quotes and fee profiles for quote-backed orders and
    transfers

    - **P2P/B2B transfers**: Internal and external stablecoin sends (USDT/USDC)
    with optional pricing snapshots

    - **Stablecoin swaps**: Treasury-backed two-leg USDT ↔ USDC conversion with
    BitGo confirmation, inventory reservation, and automatic refunds

    - **Multisig**: Collaborative and platform-managed multisig flows for
    high-value B2B
  version: 1.1.0
servers:
  - url: https://crypto.westminister.tech
    description: Production API (requires DNS for this hostname).
  - url: http://13.42.110.185:8080
    description: >-
      UAT on EC2 (direct). Use this base when building proof PDF URLs if the
      production hostname does not resolve.
security: []
tags:
  - name: Pricing
    description: >-
      Commercial pricing profiles and FX rate quotes (admin). Used with orders
      and transfers for auditable snapshots.
  - name: Transfers
    description: >-
      P2P and B2B stablecoin transfers (USDT/USDC). Optional fiat-equivalent
      pricing fields. B2B multisig behavior depends on wallet registration
      (synchronous completion vs proposal flow).
  - name: Stablecoin Swaps
    description: >-
      Treasury-backed USDT ↔ USDC conversions for BitGo provider-managed wallets
      on `tron`, `ethereum`, or `solana`. Collection confirms before treasury
      payout starts. Completion requires both legs and dual-asset balance
      synchronization.
  - name: Multisig
    description: >-
      Multisig wallet registration and TRON proposal/confirm flows
      (vendor/admin).
  - name: Escrow Wallets
    description: Escrow pool wallet metadata for off-ramp and operations.
  - name: Users
    description: >-
      User-related operations (registration, lookup, updates, counts, status
      changes)
  - name: Wallets-Users
    description: User wallet operations (create, manage, query balances)
  - name: Offers
    description: Offer operations (create, read, list, counts)
  - name: Orders
    description: Order operations (create, update, list, counts, stats)
  - name: Payment
    description: Payment initiation operations
  - name: Merchants
    description: >
      Merchant (vendor) onboarding and hierarchy operations.

      USE **GET /API/V1/AUTH/MERCHANTS** WITH **PAGE_ID** AND **PAGE_SIZE** TO
      PAGE MASTER VENDORS.

      USE **GET /API/V1/AUTH/MERCHANTS/{MERCHANT_ID}** FOR ONE MASTER VENDOR,
      **MERCHANT_WALLETS**, AND ALL **SUBVENDOR** ROWS WITH **WALLETS** (FULL
      TREE).
  - name: OTC Deposits
    description: >
      OTC fiat-to-crypto deposits (bank or mobile money). Rows live in
      **`otc_deposits`**. Merchants create drafts or one-shot deposits.
      **admin**, **otc_officer**, or **treasury** list all deposits.

      B2B bank flow uses draft, quote, submit, proof, assign, claim, settlement,
      and audit. **`credited_to_address`** is the merchant on-chain wallet
      treasury credits (resolved from the default wallet for
      **`requested_network`** on the master merchant ledger user or any
      **sub-vendor** under that merchant).

      **`GET /api/v1/auth/otc/deposits`** backfills missing
      **`credited_to_address`**/**`to_wallet_id`** when a wallet can be
      resolved. One-shot **`POST /api/v1/auth/otc/deposits`** persists the
      payout address when **`requested_network`** is sent.

      Bank proof PDFs upload via `POST .../proof` and are viewed at **`GET
      /otc-deposits-proof/{deposit_id}/{file}.pdf`** (relative
      **`proof_url`**/**`file_url`** plus API base URL).

      Merchants may edit tab-1 draft fields with **`PATCH
      /api/v1/auth/otc/deposits/{id}/draft`** while **`status`** is **`draft`**.
  - name: OTC Withdrawals
    description: >-
      OTC crypto-to-fiat withdrawals (bank or mobile money). Merchants create.
      Admin approves and executes.
  - name: OTC Config
    description: OTC display config (bank details, mobile money paybill) for merchant UI
  - name: Fiat Currencies
    description: >
      Shared platform **fiat_currencies** catalog. **GET
      /api/v1/auth/fiat-currencies** lists active rows for UI pickers. **GET
      /api/v1/auth/fiat-currencies/admin** lists all rows including inactive
      (admin). Admin manages rows with **GET
      /api/v1/auth/fiat-currencies/{id}**, **POST
      /api/v1/auth/fiat-currencies**, **PATCH
      /api/v1/auth/fiat-currencies/{id}**, and **DELETE
      /api/v1/auth/fiat-currencies/{id}**. Use for OTC, pricing, orders,
      remittance, and backoffice — not under **`/otc/...`**. Prefer **PATCH**
      with **`is_active: false`** over delete when a currency is referenced.
  - name: Countries
    description: >-
      Shared platform **countries** catalog. Public **GET /api/v1/countries**
      lists active rows for pickers. Auth **GET /api/v1/auth/countries** returns
      the same active catalog. Admin manages rows with **GET
      /api/v1/auth/countries/admin**, **GET /api/v1/auth/countries/{id}**,
      **POST /api/v1/auth/countries**, **PATCH /api/v1/auth/countries/{id}**,
      and **DELETE /api/v1/auth/countries/{id}**.
  - name: Files
    description: Authenticated file uploads for OTC receipts and proof artifacts.
paths:
  /api/v1/auth/merchants:
    post:
      tags:
        - Merchants
      summary: Create Master Merchant (Vendor) With Default Wallets
      description: >
        Creates a new **master merchant** (vendor user) and best-effort
        provisions default custodial wallets on **ethereum**, **tron**, and
        **solana**.


        **Duplicate contact guard:** Returns **409** when **email** or
        **phone_number** is already registered. No user row and no wallets are
        created.


        Wallet provisioning is **best-effort**: if one network fails (for
        example BitGo `hteth` quota), the API still creates wallets on the other
        networks and returns **`wallet_errors`** plus a **`warning`**. This
        applies only after the merchant user is created successfully.


        - Role is always set to `vendor`

        - `parent_vendor_id` is `null` for master merchants

        - Default wallets (best-effort, one per network):
          - Ethereum wallet (`is_default=true`)
          - TRON wallet
          - Solana wallet (BitGo custody required)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
                - phone_number
                - first_name
                - last_name
                - password
                - kyc_status
              properties:
                email:
                  type: string
                  format: email
                phone_number:
                  type: string
                  description: E.164 format (e.g. +2547xxxxxxx)
                first_name:
                  type: string
                last_name:
                  type: string
                password:
                  type: string
                  format: password
                  description: Merchant password (min 6 chars).
                kyc_status:
                  type: string
                  enum:
                    - pending
                    - approved
                    - rejected
                is_active:
                  type: boolean
                  default: true
                pin:
                  type: string
                  pattern: ^[0-9]{6}$
                  description: Optional 6-digit PIN for PIN-based login.
            example:
              email: merchant1@gmail.com
              phone_number: '+254700000011'
              first_name: Alice
              last_name: Merchant
              password: secret
              kyc_status: pending
              is_active: true
              pin: '123456'
      responses:
        '201':
          description: Merchant created with wallets
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  merchant:
                    $ref: '#/components/schemas/Merchant'
                  wallets:
                    type: array
                    items:
                      $ref: '#/components/schemas/MerchantWalletSummary'
                  warning:
                    type: string
                    description: >-
                      Present when one or more default wallets failed. Create
                      missing wallets manually.
                  wallet_errors:
                    type: array
                    items:
                      $ref: '#/components/schemas/DefaultWalletFailure'
              example:
                message: Merchant created successfully with default wallets
                merchant:
                  id: a2aeca1d-9686-4158-b4be-d0a3fd04760e
                  email: merchant1@gmail.com
                  phone_number: '+254700000011'
                  first_name: Alice
                  last_name: Merchant
                  role: vendor
                  kyc_status: pending
                  is_active: true
                  parent_vendor_id: null
                wallets:
                  - id: ee7104ad-4ac4-4a9f-aee5-3b0445c3b0d9
                    network: ethereum
                    address: 8.481441789197193e+47
                    is_default: true
                    wallet_type: hot
                  - id: 4284c38a-4d09-4534-8e9e-43ba65b66ef0
                    network: tron
                    address: TSQLub2pZZTmiBf1GUbJpjsx48dnuBj3nY
                    is_default: false
                    wallet_type: hot
                  - id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                    network: solana
                    address: 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU
                    is_default: false
                    wallet_type: hot
        '409':
          description: Email or phone_number already registered
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
              example:
                error: email is already registered
      security:
        - bearerAuth: []
components:
  schemas:
    Merchant:
      type: object
      description: Merchant user summary (master **vendor** or **subvendor** branch).
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        phone_number:
          type: string
        first_name:
          type: string
        last_name:
          type: string
        role:
          type: string
          enum:
            - vendor
            - subvendor
        kyc_status:
          type: string
        is_active:
          type: boolean
        parent_vendor_id:
          type: string
          format: uuid
          nullable: true
          description: >-
            Null for master merchants. Set to the master vendor id for
            sub-merchants.
    MerchantWalletSummary:
      type: object
      properties:
        id:
          type: string
          format: uuid
        network:
          type: string
          enum:
            - ethereum
            - tron
            - solana
        address:
          type: string
        alias:
          type: integer
          format: int64
        is_default:
          type: boolean
        wallet_type:
          type: string
    DefaultWalletFailure:
      type: object
      description: Per-network error when default wallet provisioning fails for one chain.
      properties:
        network:
          type: string
          enum:
            - ethereum
            - tron
            - solana
        error:
          type: string
          description: Error message from the failed wallet create attempt.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: PASETO

````