> ## 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 Offer (On-Ramp Or Off-Ramp)

> Authenticated **customer**, **vendor**, **subvendor**, **merchant**, or **admin** may create an offer. Non-admin callers must set `vendor_id` to their own user id.

**Off-ramp (`offer_type` BUY)** offers require `pricing_profile_id`, `fx_rate_quote_id`, and `default_fee_bearer`.
Create the pricing profile and FX quote first (admin). The profile and quote must both be `flow_type: offramp`,
match the offer `asset`, agree on `fiat_currency` when the profile sets it, match `network` when both set it,
and use the same `spread_bps`.
**On-ramp (`offer_type` SELL)** must omit those three fields. Orders created against a BUY offer inherit
`default_fee_bearer` when the client omits `fee_bearer` on the order.

**`rate`:** Required for **SELL**. For **BUY**, omit `rate` to store the linked FX quote's **`applied_rate`**, or send `rate` to override (e.g. Merchant display price).




## OpenAPI

````yaml /openapi.yaml post /api/v1/auth/offers
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/offers:
    post:
      tags:
        - Offers
      summary: Create Offer (On-Ramp Or Off-Ramp)
      description: >
        Authenticated **customer**, **vendor**, **subvendor**, **merchant**, or
        **admin** may create an offer. Non-admin callers must set `vendor_id` to
        their own user id.


        **Off-ramp (`offer_type` BUY)** offers require `pricing_profile_id`,
        `fx_rate_quote_id`, and `default_fee_bearer`.

        Create the pricing profile and FX quote first (admin). The profile and
        quote must both be `flow_type: offramp`,

        match the offer `asset`, agree on `fiat_currency` when the profile sets
        it, match `network` when both set it,

        and use the same `spread_bps`.

        **On-ramp (`offer_type` SELL)** must omit those three fields. Orders
        created against a BUY offer inherit

        `default_fee_bearer` when the client omits `fee_bearer` on the order.


        **`rate`:** Required for **SELL**. For **BUY**, omit `rate` to store the
        linked FX quote's **`applied_rate`**, or send `rate` to override (e.g.
        Merchant display price).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - vendor_id
                - offer_type
                - asset
                - crypto_amount
                - available_amount
                - min_order
                - max_order
              properties:
                vendor_id:
                  type: string
                  format: uuid
                offer_type:
                  type: string
                  enum:
                    - SELL
                    - BUY
                  description: >-
                    SELL = Merchant sells USDT (on-ramp), BUY = Merchant buys
                    USDT (off-ramp)
                asset:
                  type: string
                crypto_amount:
                  type: string
                  description: Total offer amount for selected asset (USDT or USDC).
                usdt_amount:
                  type: string
                  deprecated: true
                  description: Deprecated alias for crypto_amount.
                available_amount:
                  type: string
                rate:
                  type: string
                  description: >-
                    KES per USDT. Required for SELL. For BUY, omit to use the
                    linked FX quote applied_rate, or set to override.
                min_order:
                  type: string
                max_order:
                  type: string
                status:
                  type: string
                  description: 'Optional: defaults to ''active'' if omitted'
                description:
                  type: string
                pricing_profile_id:
                  type: string
                  format: uuid
                  description: Required for BUY. Omit for SELL.
                fx_rate_quote_id:
                  type: string
                  format: uuid
                  description: Required for BUY. Omit for SELL.
                default_fee_bearer:
                  type: string
                  enum:
                    - sender
                    - receiver
                  description: >-
                    Required for BUY. Default for orders from this offer. Omit
                    for SELL.
            examples:
              on_ramp_offer:
                summary: >-
                  On-Ramp Offer (Merchant/Vendor Sells USDT/USDC, Customer Buys
                  USDT/USDC)
                value:
                  vendor_id: 5c81c005-1c52-4e0d-85e2-862ee1cdd4d0
                  offer_type: SELL
                  asset: USDT
                  crypto_amount: '7999.99'
                  available_amount: '8000.00'
                  rate: '141.00'
                  min_order: '10'
                  max_order: '1500.00'
                  status: active
                  description: Ethereum On-Ramp Offer - Instant USDT/USDC Delivery
              remittance_off_ramp_buy:
                summary: >-
                  Remittance Off-Ramp (BUY) USDT on Ethereum to KES — requires
                  admin pricing profile + FX quote first
                value:
                  vendor_id: 7a4301b0-e04b-4102-a999-b17dada65509
                  offer_type: BUY
                  asset: USDT
                  crypto_amount: '10000'
                  available_amount: '2500'
                  min_order: '50'
                  max_order: '2500'
                  status: active
                  description: >-
                    Off-ramp remittance — USDT on Ethereum. KES payout (mobile
                    money)
                  pricing_profile_id: a1111111-1111-1111-1111-111111111111
                  fx_rate_quote_id: b2222222-2222-2222-2222-222222222222
                  default_fee_bearer: receiver
      responses:
        '201':
          description: Offer Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Offer'
              examples:
                on_ramp_response:
                  summary: On-Ramp Offer Response
                  value:
                    id: 7c9a9311-7e7d-4739-9abc-34f7db00ff19
                    vendor_id: 5c81c005-1c52-4e0d-85e2-862ee1cdd4d0
                    offer_type: SELL
                    asset: USDT
                    crypto_amount: '7999.99000000'
                    available_amount: '8000.00000000'
                    rate: '141.00'
                    min_order: '10.00000000'
                    max_order: '1500.00000000'
                    status: active
                    description:
                      String: Ethereum On-Ramp Offer - Instant USDT/USDC Delivery
                      Valid: true
                    created_at: '2025-12-12T10:30:00.000000Z'
                    updated_at: '2025-12-12T10:30:00.000000Z'
                off_ramp_response:
                  summary: Off-Ramp Offer Response
                  value:
                    id: 0e16f8d4-e557-4343-848b-9be955ccf06c
                    vendor_id: 7a4301b0-e04b-4102-a999-b17dada65509
                    offer_type: SELL
                    asset: USDT
                    crypto_amount: '799.99000000'
                    available_amount: '800.00000000'
                    rate: '141.00'
                    min_order: '10.00000000'
                    max_order: '1500.00000000'
                    status: active
                    description:
                      String: Tron Off-Ramp Offer – Instant USDT/USDC Delivery
                      Valid: true
                    created_at: '2025-12-12T15:31:43.694502Z'
                    updated_at: '2025-12-12T15:31:43.694502Z'
                    deleted_at:
                      Time: '0001-01-01T00:00:00Z'
                      Valid: false
      security:
        - bearerAuth: []
components:
  schemas:
    Offer:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Offer ID.
        vendor_id:
          type: string
          format: uuid
          description: Vendor ID.
        offer_type:
          type: string
          enum:
            - SELL
            - BUY
          description: Offer type.
        asset:
          type: string
          description: Asset symbol (e.g.
          USDT).: null
        crypto_amount:
          type: string
          description: Offer amount in selected asset (USDT/USDC).
        available_amount:
          type: string
          description: >-
            Available offer amount in selected asset. Must be <= crypto_amount
            and <= owner's default wallet asset balance.
        rate:
          type: string
          description: Exchange rate (KES per USDT).
        min_order:
          type: string
          description: Minimum order size.
        max_order:
          type: string
          description: Maximum order size.
        status:
          type: string
          description: Offer status.
        pricing_profile_id:
          type: string
          format: uuid
          nullable: true
          description: Set for BUY (off-ramp) offers.
        fx_rate_quote_id:
          type: string
          format: uuid
          nullable: true
          description: Set for BUY (off-ramp) offers.
        default_fee_bearer:
          type: string
          enum:
            - sender
            - receiver
          nullable: true
          description: Default fee bearer for orders against this offer.
        description:
          type: object
          properties:
            String:
              type: string
              nullable: true
            Valid:
              type: boolean
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        deleted_at:
          $ref: '#/components/schemas/NullableTime'
    NullableTime:
      type: object
      description: Database-style nullable time wrapper
      properties:
        Time:
          type: string
          format: date-time
          nullable: true
        Valid:
          type: boolean
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: PASETO

````