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

# Off-Ramp

Off-ramp lets you turn stablecoins (USDT/USDC, digital dollars that hold a
steady value) into Gambian Dalasi (GMD). You tell us how much dalasi you want,
we give you a stablecoin address to pay, and once it's paid we hand over the
dalasi, either into your Modem Pay balance or straight to a mobile money wallet.

<Note>Off-ramp only works in live mode. Use a live API key.</Note>

## How it works

<Steps>
  <Step title="Create an off-ramp request">
    Tell us how much dalasi you want and where to send it. We give you back a
    stablecoin address and the exact amount to pay.
  </Step>

  <Step title="Pay the stablecoin amount">
    Send the quoted USDT/USDC to that address. The payment can come in one
    transfer or several.
  </Step>

  <Step title="We hand over the dalasi">
    Once it's paid, we add the dalasi to your balance or pay it out to the
    mobile money wallet you chose.
  </Step>
</Steps>

## Create an off-ramp

<ParamField body="gmd_amount" type="number" required>
  How much Gambian Dalasi you want to receive.
</ParamField>

<ParamField body="pay_currency" type="string" default="USDT">
  Which stablecoin you'll pay with. Defaults to `USDT`.
</ParamField>

<ParamField body="network" type="string" default="TRC20">
  Which network the payment goes over. Defaults to `TRC20`.
</ParamField>

<ParamField body="destination" type="modempay_balance | mobile_money">
  Where the dalasi ends up. Either `modempay_balance` (added to your balance) or
  `mobile_money` (paid out to a wallet). Defaults to your balance.
</ParamField>

<ParamField body="payout_method" type="object">
  Only needed when `destination` is `mobile_money`. This is the wallet to pay
  out to.

  <Expandable title="payout_method">
    <ParamField body="network" type="wave | afrimoney" required>
      The mobile money provider, e.g. `wave`.
    </ParamField>

    <ParamField body="account_number" type="string" required>
      The wallet number that should receive the dalasi.
    </ParamField>

    <ParamField body="account_name" type="string" required>
      The name on the account.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="callback_url" type="string">
  A web address where you want to be notified about this off-ramp.
</ParamField>

<Note>
  `payout_method` is optional. Leave it out to send the dalasi to your Modem Pay
  balance; include it (with `destination: "mobile_money"`) to pay out to a
  wallet.
</Note>

### Send the dalasi to your Modem Pay balance

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.modempay.com/v1/minting/offramp \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "gmd_amount": 1000
    }'
  ```

  ```typescript nodejs theme={null}
  const offramp = await modempay.offramp.create({
    gmd_amount: 1000,
  });
  ```
</CodeGroup>

### Send the dalasi straight to a mobile money wallet

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.modempay.com/v1/minting/offramp \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "gmd_amount": 1000,
      "destination": "mobile_money",
      "payout_method": {
        "network": "wave",
        "account_number": "7000000",
        "account_name": "Account Holder"
      }
    }'
  ```

  ```typescript nodejs theme={null}
  const offramp = await modempay.offramp.create({
    gmd_amount: 1000,
    destination: "mobile_money",
    payout_method: {
      network: "wave",
      account_number: "7000000",
      account_name: "Account Holder",
    },
  });
  ```
</CodeGroup>

**What you get back**

```json json theme={null}
{
  "id": "b7c93f02-1a4e-4d8c-9f31-2e6a5d8c41bb",
  "provider_fee": 0,
  "actually_paid": 0,
  "fee_bearer": "business",
  "business_id": "8a8d29ad-7e3c-445d-9732-51893ffcfb7d",
  "account_id": "f3ae3627-a381-479e-ac7e-c9c62fcd0225",
  "direction": "off_ramp",
  "destination": "mobile_money",
  "payout_method": {
    "network": "wave",
    "account_name": "Account Holder",
    "account_number": "7000000"
  },
  "gmd_amount": 1000,
  "gmd_rate": 74.2297,
  "fee": 0.14,
  "fee_currency": "USD",
  "pay_amount": 13.62,
  "pay_currency": "USDT",
  "pay_address": "TXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "network": "TRC20",
  "provider_payment_id": "9f2c7b81-3d5a-4e6f-8a2b-1c4d7e9f0a3b",
  "invoice_expires_at": "2026-01-01T00:30:00.000Z",
  "status": "pending",
  "reference": "MP-XXXXXXXX-XXXXXX-XXXXXXXX",
  "test_mode": false,
  "markup_share_usd": 0,
  "markup_config": null,
  "events": {
    "2026-01-01T00:00:00.000Z": {
      "source": "system.create_off_ramp",
      "status": "pending"
    }
  },
  "metadata": {
    "gmd_rate": 74.2297,
    "usd_equivalent": 13.47
  },
  "updatedAt": "2026-01-01T00:00:00.000Z",
  "createdAt": "2026-01-01T00:00:00.000Z",
  "provider_invoice_id": null,
  "invoice_url": null,
  "failure_reason": null,
  "credit_transaction_id": null,
  "quote_id": null
}
```

The fields that matter:

* **`pay_address`** — send the stablecoin to this address.
* **`pay_amount`** + **`pay_currency`** — the exact amount and coin to send.
* **`gmd_amount`** — the dalasi you'll receive.
* **`invoice_expires_at`** — pay before this time.
* **`status`** — starts out as `pending`.

## Paying

Send `pay_amount` of `pay_currency` to `pay_address` before
`invoice_expires_at`.

<Warning>
  **The payment might arrive in more than one transfer.** The payer can send it
  in parts. We hand over the dalasi bit by bit as the money comes in, and finish
  once the full amount has arrived. Follow along using the `status` field and
  the notifications (below) rather than expecting one single payment.
</Warning>

## Status values

<ParamField body="pending" type="status">
  Created, waiting for payment.
</ParamField>

<ParamField body="underpaid" type="status">
  Some money has come in, but not the full amount yet.
</ParamField>

<ParamField body="paid" type="status">
  Fully paid; dalasi handed over.
</ParamField>

<ParamField body="overpaid" type="status">
  Paid more than needed; dalasi handed over.
</ParamField>

<ParamField body="expired" type="status">
  Not paid (or not fully paid) before the deadline.
</ParamField>

## Look up an off-ramp

Check the current state of an off-ramp using its `id`. Handy for seeing the
`status`, how much has been paid (`actually_paid`), and the settlement details.

```bash cURL theme={null}
curl https://api.modempay.com/v1/minting/ramps/b7c93f02-1a4e-4d8c-9f31-2e6a5d8c41bb \
  -H "Authorization: Bearer YOUR_API_KEY"
```

This gives you back the same details as when you created it, showing the latest
state — including the updated `status`, `actually_paid`, and `events`.

## Notifications (webhooks)

Set a `callback_url` to get updates as the off-ramp moves along. You may get
more than one update as partial payments come in and the dalasi is handed over.

To confirm a notification really came from Modem Pay, see the
[Webhooks guide](/documentation/core/webhooks).

## If a mobile money payout fails

When `destination` is `mobile_money`, we try to pay the dalasi to the wallet in
`payout_method`. If that payout fails for any reason (say the provider is down
or the wallet number is wrong), the money is **added to your Modem Pay balance
instead**, it's never lost. You can then try the payout again from your
balance, or fix the wallet details and pay out again.

<Note>
  A failed mobile money payout always falls back to your `modempay_balance`. So
  money from a confirmed payment is safe even if the wallet payout doesn't go
  through.
</Note>

## Good to know

* `pay_amount` is worked out from `gmd_amount`, the current `gmd_rate`, and the
  `fee`. The rate is locked in the moment you create the request.
* Sending dalasi to a mobile money wallet needs `payout_method`; sending it to
  your balance does not.
* To resell off-ramp on your own platform and earn a margin, see
  [Off-Ramp for Resellers](/documentation/defi/offramp-resellers).
