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

# Stablecoin to KES

> Convert stablecoin (USDC, USDT) to Kenyan shilling.

**POST `/offramp/initiate`** endpoint creates an off-ramp transaction where the customer sends stablecoin and receives Kenyan shilling (KES) instantly.

Switch returns a deposit address — once the customer sends the amount in the specified asset to that address, the KES payout is processed automatically.

<Note>
  Before calling this endpoint to create a payment, call `GET /requirement` to
  retrieve the required beneficiary fields based on the country and channel.
</Note>

## Example request

<CodeGroup>
  ```bash cURL theme={"dark"}
  curl https://api.onswitch.xyz/offramp/initiate \
    --request POST \
    --header 'Content-Type: application/json' \
    --header 'x-service-key: '"$YOUR_SERVICE_KEY" \
    --data '{
    "country": "KE",
    "currency": "KES",
    "amount": 12,
    "asset": "base:usdc",
    "narration": "Mobile money transfer to John Doe",
    "channel": "MOBILEMONEY",
    "beneficiary": {
      "mobile_network": "MPESA",
      "mobile_number": "254712345678",
      "holder_name": "John Doe",
      "holder_type": "INDIVIDUAL"
    }
  }'
  ```

  ```javascript Node.js theme={"dark"}
  const res = await fetch('https://api.onswitch.xyz/offramp/initiate', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-service-key': process.env.YOUR_SERVICE_KEY,
    },
    body: JSON.stringify({
      country: 'KE',
      currency: 'KES',
      amount: 12,
      asset: 'base:usdc',
      narration: 'Mobile money transfer to John Doe',
      channel: 'MOBILEMONEY',
      beneficiary: {
        mobile_network: 'MPESA',
        mobile_number: '254712345678',
        holder_name: 'John Doe',
        holder_type: 'INDIVIDUAL',
      },
    }),
  });

  const json = await res.json();
  console.log(json.data?.reference, json.data?.status);

  ```

  ```python Python theme={"dark"}
  import json
  import os
  import urllib.request

  payload = {
      "country": "KE",
      "currency": "KES",
      "amount": 12,
      "asset": "base:usdc",
      "narration": "Mobile money transfer to John Doe",
      "channel": "MOBILEMONEY",
      "beneficiary": {
          "mobile_network": "MPESA",
          "mobile_number": "254712345678",
          "holder_name": "John Doe",
          "holder_type": "INDIVIDUAL",
      },
  }

  req = urllib.request.Request(
      "https://api.onswitch.xyz/offramp/initiate",
      method="POST",
      data=json.dumps(payload).encode("utf-8"),
      headers={
          "Content-Type": "application/json",
          "x-service-key": os.environ["YOUR_SERVICE_KEY"],
      },
  )

  with urllib.request.urlopen(req, timeout=60) as r:
      out = json.load(r)
      data = out.get("data") or {}
      print(data.get("reference"), data.get("status"))
  ```
</CodeGroup>

## Frequently Asked Questions

<AccordionGroup>
  <Accordion title="Exact destination amount" icon="circle-dollar-sign">
    Add exact\_output and amount if you want an exact amount to be received at the destination. e.g; if you want 10,000 KES

    ```json theme={"dark"}
    {
      "exact_output": true,
      "amount": 10000
    }
    ```
  </Accordion>

  <Accordion title="Webhook URL" icon="webhook">
    Add callback\_url to set the URL to receive webhook notifications when the payment status changes.

    ```json theme={"dark"}
    {
      "callback_url": "https://your-webhook-url.com"
    }
    ```
  </Accordion>

  <Accordion title="Developer fee" icon="percent">
    Add developer\_fee and developer\_recipient to set the developer fee you wish to charge from the payment amount.

    ```json theme={"dark"}
    {
      "developer_fee": 0.5,
      "developer_recipient": "0x1234567890123456789012345678901234567890"
    }
    ```
  </Accordion>

  <Accordion title="Beneficiary type" icon="user">
    Include **`holder_type`** on **`beneficiary`** depending on the payout recipient; if Business, set to **`BUSINESS`** else **`INDIVIDUAL`**.

    ```json theme={"dark"}
    {
      "beneficiary": {
        "holder_type": "INDIVIDUAL"
      }
    }
    ```
  </Accordion>

  <Accordion title="Payment reason" icon="file-text">
    Add reason to set the purpose of the payment. This is mostly required for transfers out of Nigeria.

    ```json theme={"dark"}
    {
      "reason": "CAPITAL_CONTRIBUTIONS"
    }
    ```

    Allowed values are listed under [Reason](/reasons).
  </Accordion>

  <Accordion title="Refund address" icon="wallet">
    Add refund\_address to set the wallet address to refund the stablecoin deposit to if the payment fails for any reason.

    ```json theme={"dark"}
    {
      "refund_address": "0x1234567890123456789012345678901234567890"
    }
    ```
  </Accordion>

  <Accordion title="Settlement channel" icon="landmark">
    Add channel to set the specific channel or settlement method to use for the payment, if not set, the default channel for the country will be used.

    ```json theme={"dark"}
    {
      "channel": "MOBILEMONEY"
    }
    ```

    Allowed values are listed under [Countries](/countries).
  </Accordion>

  <Accordion title="Reusable deposit address" icon="map-pin">
    Add static if you want to always generate the same deposit address for the same local currency beneficiary details.

    ```json theme={"dark"}
    {
      "static": true
    }
    ```
  </Accordion>
</AccordionGroup>

### Example response

```json theme={"dark"}
{
  "success": true,
  "message": "Offramp initiated successfully",
  "timestamp": "2026-03-31T04:03:15.931Z",
  "data": {
    "status": "AWAITING_DEPOSIT",
    "type": "OFFRAMP",
    "reference": "6c01338d-67e5-4d0c-a394-9d3e367f46a5",
    "rate": 128.5,
    "source": {
      "amount": 12,
      "currency": "USDC",
      "network": "BASE"
    },
    "destination": {
      "amount": 1542,
      "currency": "KES",
      "network": "FIAT"
    },
    "deposit": {
      "amount": 12,
      "address": "0xcd257a5867B42556fa14c35de714154B277f70fD",
      "asset": "base:usdc",
      "note": [
        "Kindly send the exact amount to the wallet address to complete the transaction.",
        "This dynamic wallet address has a 30 minutes expiry window and can only be used once."
      ]
    }
  }
}
```

## Completing the Deposit

After initiating, you are expected to send **exactly** **`deposit.amount`** of **`deposit.asset`** to **`deposit.address`**. Check **`deposit.note`** for specific instructions.

<Warning>
  The deposit address is for **one-time use only** and expires after **30
  minutes**. if not created with **`static`** set to **`true`**.
</Warning>

If less or more amount than specified in **`deposit.amount`** is sent, the deposit will be processed based on the amount sent, so long as it is within the limits and the asset (**`deposit.asset`**) sent is supported.

## Need Help?

<CardGroup cols={2}>
  <Card title="Email Support" icon="mail" href="mailto:contact@onswitch.xyz">
    Send us a message.
  </Card>

  <Card title="Book a call" icon="calendar" href="https://calendly.com/contact-onswitch/30min">
    Hop on a call with us.
  </Card>
</CardGroup>
