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

# Swap USDC to USDT

> Swaps one stablecoin for the other on the customer's smart-contract wallet via the FiatSwapV2 DEX router. Gas is sponsored by the paymaster; Rach's per-chain fee is deducted from the input amount and routed to treasury in the same atomic UserOperation. The response is `202 Accepted` with a `swap_id` — poll `GET /v1/swaps/{id}` or subscribe to the `swap.settled` / `swap.failed` webhooks for the terminal result and on-chain tx hash. Test keys (`rach_sk_test_`) return a simulated result without touching the chain.



## OpenAPI

````yaml /api-reference/caas-openapi.json post /v1/swaps
openapi: 3.0.0
info:
  description: >-
    Rach CaaS is the stablecoin infrastructure layer for African fintechs and
    financial institutions. It enables any business to offer their customers
    non-custodial USDC and USDT wallets, instant on-chain transfers, and fiat ↔
    stablecoin conversion in any supported currency (XOF, XAF, NGN, GHS, ...) —
    without building blockchain infrastructure.


    **Stablecoins:** USDC and USDT are supported equally everywhere. On any
    endpoint that moves value — `POST /v1/users/fund`, `POST
    /v1/transfers/send`, `POST /v1/users/withdraw` — set the token
    (`target_token` / `token`, or the ticker inside a
    `DIRECT_CRYPTO:{USDC|USDT}:{amount}` quote). `GET /v1/users/balance` returns
    both `balance_usdc` and `balance_usdt`.


    **System-wide phone addressing:** wallets are keyed by phone number and
    belong to the system, not to any one business. Money moves freely across
    businesses — and to phone numbers that have never been provisioned: Rach
    creates the wallet on the fly and notifies the recipient by SMS with USSD
    access instructions.


    **Network:** Polygon PoS (Chain ID 137). All smart contract wallets,
    transfers, and withdrawals settle on Polygon mainnet. Test environments use
    Sepolia (Chain ID 11155111).


    ## Authentication

    **B2B API endpoints** (`/v1/users/*`, `/v1/transfers/*`, `/v1/fx/*`) use API
    Key authentication. Pass your key in the `X-API-Key` header. Keys are
    prefixed `rach_sk_live_` (mainnet) or `rach_sk_test_` (sandbox — no on-chain
    execution).


    **Dashboard endpoints** (`/v1/dashboard/*`) use JWT Bearer authentication.
    Your JWT must include `business_id` and the `waas` permission scope.


    ## Sandbox Mode

    All B2B endpoints honour test-mode API keys (`rach_sk_test_*`). In sandbox
    mode every operation returns an immediate success response
    (`SANDBOX_SIMULATED`) without touching the blockchain or debiting your
    treasury balance. Use sandbox keys for integration testing and CI.


    ## Typical Integration Flow

    1. `POST /v1/users/provision` — create a non-custodial SCW for each end-user
    (offline, no gas)

    2. Collect fiat from customer → deposit to Rach bank account → `POST
    /v1/dashboard/treasury/topup`

    3. Rach confirms XOF receipt → `POST
    /v1/dashboard/treasury/topup/{id}/confirm` (credits your USDC balance)

    4. `POST /v1/users/fund` — transfer USDC from your treasury balance to the
    customer SCW on-chain

    5. `GET /v1/users/balance` — read live on-chain USDC balance via Polygon RPC

    6. `POST /v1/transfers/send` — instant peer-to-peer USDC transfer between
    customer SCWs (ERC-4337 UserOp)

    7. `POST /v1/users/withdraw` — off-ramp: sweep USDC from SCW back to Rach
    treasury; Rach pays out XOF via mobile money


    ## System-Wide Wallets & Multi-Membership

    A wallet is keyed by phone number and belongs to the **system**, not to any
    one business. Several businesses can operate the same wallet — but only with
    the customer's consent.


    **Provisioning outcomes** (`POST /v1/users/provision`):

    - `PROVISIONED` — new wallet created; you are its first member.

    - `ADOPTED` — the phone had an unaffiliated wallet (created on the fly by an
    inbound transfer); you are now its primary member.

    - `ALREADY_EXISTS` — the wallet exists and you already operate it.

    - `LINK_REQUIRED` — the wallet belongs to another business. You get the same
    address back but **no operating rights**. Start the consent flow to gain
    them.


    **Consent-based linking** (to operate a wallet another business created):

    1. `POST /v1/users/link/request` — a one-time code is SMSed to the customer.

    2. `POST /v1/users/link/confirm` — submit the code the customer gives you;
    you become a member. Existing members receive a `user.linked` webhook.


    **Money-in is open, money-out is gated.** Any business can fund a wallet or
    send money to it (paid from the sender's own ledger). Only a **member** may
    originate transfers, withdraw, or change the phone number for a wallet.


    **Consent-gated phone change** (`POST /v1/users/phone-change/request` →
    `/confirm`): a one-time code is SMSed to the NEW number (proving SIM
    control). The SCW address, balance and history are preserved; every member
    receives a `user.phone_changed` webhook.


    ## Webhook Events

    Signed with HMAC-SHA256 over the body in the `X-Rach-Signature: sha256=...`
    header (key = your webhook secret).

    - `transfer.received` — a wallet you operate received an inbound transfer.

    - `user.linked` — a new business was granted operating rights on a wallet
    you operate.

    - `user.phone_changed` — the phone number of a wallet you operate was
    re-keyed (address unchanged).


    ## Multi-Currency

    Rach moves any fiat; USDC is the settlement rail. Rates are per-currency
    (XOF, XAF, NGN, GHS, ...). See `GET /v1/dashboard/rates`. Topup quotes and
    withdrawals carry a `currency_code` / `payout_currency`.


    ## Status Lifecycles

    **Deposit:** `QUEUED` → `SETTLED`

    **Transfer:** `QUEUED` → `SUBMITTED` → `SETTLED`

    **Withdrawal:** `PENDING` → `SUBMITTED` → `CRYPTO_RECEIVED` → `COMPLETED`
  title: Rach CaaS — Crypto-as-a-Service API
  contact:
    name: Rach Finance Support
    url: https://rach.finance
  version: 1.0.1
servers:
  - url: https://api.rach.finance/caas/api
security: []
paths:
  /v1/swaps:
    post:
      tags:
        - Swaps
      summary: Swap USDC to USDT
      description: >-
        Swaps one stablecoin for the other on the customer's smart-contract
        wallet via the FiatSwapV2 DEX router. Gas is sponsored by the paymaster;
        Rach's per-chain fee is deducted from the input amount and routed to
        treasury in the same atomic UserOperation. The response is `202
        Accepted` with a `swap_id` — poll `GET /v1/swaps/{id}` or subscribe to
        the `swap.settled` / `swap.failed` webhooks for the terminal result and
        on-chain tx hash. Test keys (`rach_sk_test_`) return a simulated result
        without touching the chain.
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/cmd_api.SwapRequest'
        description: Swap parameters
        required: true
      responses:
        '202':
          description: Accepted
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '502':
          description: Bad Gateway
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
      security:
        - ApiKeyAuth: []
components:
  schemas:
    cmd_api.SwapRequest:
      type: object
      required:
        - amount
        - idempotency_key
        - sender_phone
        - token_in
        - token_out
      properties:
        amount:
          type: string
          example: '100.00'
        idempotency_key:
          type: string
          example: swap_ref_001
        sender_phone:
          description: >-
            sender_phone accepts a 0x wallet address OR an E.164 phone
            (auto-detected).
          type: string
          example: '0xFDd4ABaF518d49A6749A3aD6A68f9403bD93cFF0'
        token_in:
          type: string
          enum:
            - USDC
            - USDT
          example: USDC
        token_out:
          type: string
          enum:
            - USDC
            - USDT
          example: USDT
  securitySchemes:
    ApiKeyAuth:
      description: >-
        Your Rach B2B API key. Use `rach_sk_live_*` for production (on-chain) or
        `rach_sk_test_*` for sandbox (no-chain simulation).
      type: apiKey
      name: X-API-Key
      in: header

````