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

# Create an order

> Create a USDC payout order to any M-Pesa, mobile money, till, paybill, or bank recipient. Returns the deposit address and exact amount to send on Base.

Validates the recipient's account, locks a quote, and returns where to send USDC. Nothing moves until you deposit.

<Warning>
  Backend only. Never call from frontend.
</Warning>

## Endpoint

```text theme={null}
POST https://merchant.minisend.xyz/api/offramp/orders
```

```text theme={null}
Authorization: Bearer ms_live_your_key_here
Idempotency-Key: payout-8412
```

Requires the `offramp` scope.

<Tip>
  Always send an `Idempotency-Key` (any string unique per payout, e.g. your payout ID). Replaying the same key returns the original order with a `200` instead of creating a duplicate, so retries on timeouts are safe.
</Tip>

## Body

<ParamField body="amount" type="number" required>
  USDC amount, 0.5 – 50,000. The local equivalent must fall inside the [per-transaction range](/offramp/overview#limits).
</ParamField>

<ParamField body="currency" type="string" required>
  Payout currency: `KES`, `NGN`, `GHS`, or `UGX`.
</ParamField>

<ParamField body="refund_address" type="string" required>
  A `0x` EVM address you control. Failed NGN payouts are refunded here automatically; it is also the return path of record for support cases.
</ParamField>

<ParamField body="recipient" type="object" required>
  Who gets paid. Shape per method in [recipients](/offramp/recipients). Validated before the order is created.
</ParamField>

<ParamField body="reference" type="string">
  Your reference (e.g. internal payout ID). Echoed back as `external_reference` in responses and webhooks.
</ParamField>

## Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://merchant.minisend.xyz/api/offramp/orders \
    -H "Authorization: Bearer ms_live_your_key_here" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: payout-8412" \
    -d '{
      "amount": 10,
      "currency": "KES",
      "refund_address": "0xYourWalletAddress0000000000000000000000",
      "reference": "payout-8412",
      "recipient": {
        "method": "MOBILE",
        "account_name": "Jane Wanjiku",
        "phone": "0712345678",
        "mobile_network": "Safaricom"
      }
    }'
  ```

  ```javascript Node.js theme={null}
  const res = await fetch('https://merchant.minisend.xyz/api/offramp/orders', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer ms_live_your_key_here',
      'Content-Type': 'application/json',
      'Idempotency-Key': 'payout-8412',
    },
    body: JSON.stringify({
      amount: 10,
      currency: 'KES',
      refund_address: '0xYourWalletAddress0000000000000000000000',
      reference: 'payout-8412',
      recipient: {
        method: 'MOBILE',
        account_name: 'Jane Wanjiku',
        phone: '0712345678',
        mobile_network: 'Safaricom',
      },
    }),
  });

  if (!res.ok) throw new Error((await res.json()).error);
  const order = await res.json();
  // send order.total_deposit_usdc USDC on Base to order.deposit_address
  ```

  ```python Python theme={null}
  import requests

  res = requests.post(
      "https://merchant.minisend.xyz/api/offramp/orders",
      headers={
          "Authorization": "Bearer ms_live_your_key_here",
          "Content-Type": "application/json",
          "Idempotency-Key": "payout-8412",
      },
      json={
          "amount": 10,
          "currency": "KES",
          "refund_address": "0xYourWalletAddress0000000000000000000000",
          "reference": "payout-8412",
          "recipient": {
              "method": "MOBILE",
              "account_name": "Jane Wanjiku",
              "phone": "0712345678",
              "mobile_network": "Safaricom",
          },
      },
  )

  res.raise_for_status()
  order = res.json()
  ```
</CodeGroup>

## Response (201)

```json theme={null}
{
  "order_id": "9b2f6c1e-...",
  "status": "pending",
  "amount_usdc": 10,
  "total_deposit_usdc": 10,
  "currency": "KES",
  "rate": 129.45,
  "amount_local": 1294,
  "fee": 13,
  "recipient_amount": 1281,
  "deposit_address": "0x8005ee53e57ab11e11eaa4efe07ee3835dc02f98",
  "deposit_chain": "base",
  "recipient": {
    "account_name": "Jane Wanjiku",
    "method": "MOBILE",
    "phone": "0712345678"
  },
  "refund_address": "0xYourWalletAddress0000000000000000000000",
  "external_reference": "payout-8412",
  "expires_at": "2026-07-05T12:30:00.000Z",
  "created_at": "2026-07-05T12:00:03.000Z",
  "instructions": "Send exactly 10 USDC (Base) to deposit_address from your own wallet, then submit the transaction hash via POST /api/offramp/orders/9b2f6c1e-.../deposit before expires_at."
}
```

<ResponseField name="order_id" type="string" required>
  Unique order identifier.
</ResponseField>

<ResponseField name="total_deposit_usdc" type="number" required>
  **The exact USDC amount to send.** Equals `amount_usdc` for KES, GHS, and UGX. For NGN it is `amount_usdc + sender_fee_usdc + transaction_fee_usdc`.
</ResponseField>

<ResponseField name="sender_fee_usdc" type="number">
  NGN orders only. A network fee included in `total_deposit_usdc`.
</ResponseField>

<ResponseField name="transaction_fee_usdc" type="number">
  NGN orders only. A network fee included in `total_deposit_usdc`.
</ResponseField>

<ResponseField name="deposit_address" type="string" required>
  Where to send USDC on Base. For KES, GHS, and UGX this is a shared settlement address; always follow your transfer with a [hash submission](/api-reference/offramp/submit-deposit). For NGN it is a **single-use** address monitored automatically.
</ResponseField>

<ResponseField name="deposit_chain" type="string" required>
  Always `base`. USDC sent on other chains is not detected.
</ResponseField>

<ResponseField name="rate" type="number" required>
  Quoted rate. For KES, GHS, and UGX the payout executes at the live rate at deposit time, and the order's `rate`, `amount_local`, and `fee` update to the executed values. For NGN the rate is locked.
</ResponseField>

<ResponseField name="expires_at" type="string" required>
  Deposit deadline, ISO 8601. 30 minutes for KES, GHS, UGX; about 5 minutes for NGN. After it passes the order becomes `expired`.
</ResponseField>

<ResponseField name="instructions" type="string" required>
  Human-readable next step for this specific order.
</ResponseField>

## Errors

| Status | Meaning                                                                                                           |
| ------ | ----------------------------------------------------------------------------------------------------------------- |
| `200`  | Replay of an existing `Idempotency-Key`. Returns the original order, not a new one                                |
| `400`  | Invalid amount, currency, `refund_address`, or recipient shape; or amount outside the local per-transaction range |
| `403`  | Key lacks the `offramp` scope or off-ramp is not enabled on your account                                          |
| `422`  | Recipient failed account validation. Nothing created                                                              |
| `502`  | Pricing or deposit-address provisioning failed. Retry with a **new**`Idempotency-Key`                             |
