# Stablecoin On/Off-Ramp

> Convert between fiat (NGN) and stablecoins (USDC or USDT).

Section: Build with AI
Source: https://coincircuit.io/docs/guides/stablecoin-onramp-offramp/
Interactive version: https://coincircuit.io/api-reference?tab=guides&guide=stablecoin-onramp-offramp

Tags: Swap, Balance, Payouts

Paste this prompt into Claude, ChatGPT, or any AI tool. It works best with the CoinCircuit MCP server connected: https://mcp.coincircuit.io

---

You are helping me build a stablecoin on-ramp and off-ramp into my existing application using CoinCircuit swaps. I have the CoinCircuit MCP server connected.

**If you have access to the CoinCircuit MCP server, call these tools for the most accurate and detailed schema outputs:**
- Call `get_api_overview` in the CoinCircuit MCP for base URLs, auth method, and available features.
- Call `search_api` with query `swap` and type `endpoints` to list all swap endpoints (estimate, quotation, execute, history).
- Call `get_endpoint` with method `get` and path `/api/v1/swap/estimate` for the indicative estimate schema.
- Call `get_endpoint` with method `post` and path `/api/v1/swap/quotation` for the locked-rate quotation schema.
- Call `get_endpoint` with method `post` and path `/api/v1/swap/execute/{quotationId}` for the execute schema.
- Call `get_endpoint` with method `get` and path `/api/v1/balance` for the balance response schema.
- Call `get_endpoint` with method `post` and path `/api/v1/payouts` for the payout (off-ramp withdrawal) schema.
- Call `get_conversion_rate` in the CoinCircuit MCP for live display rates.

Use the live MCP data as your source of truth. The details below are a guide, but if the MCP returns something different, trust the MCP.

## API Basics

- **Base URL (production):** `https://api.coincircuit.io`
- **Base URL (sandbox):** `https://sandbox-api.coincircuit.io`
- **Auth:** Pass your API key in the `x-api-key` header on every request.

## Project Context

I want users to move between fiat and stablecoins held in my CoinCircuit merchant balance:

- **On-ramp:** fiat (NGN) -> stablecoin (USDC or USDT)
- **Off-ramp:** stablecoin (USDC or USDT) -> fiat (NGN), then withdraw to a bank account

Swaps convert between two currencies in your CoinCircuit balance at a rate you lock in advance. Supported balance currencies for swaps are `NGN` and a stablecoin (`USDC` or `USDT`). The flow is always: get a quote -> lock a quotation -> execute before it expires.

## What I Need You to Implement

### 1. Check the balance

**Endpoint:** `GET /api/v1/balance?currency={currency}`
*(Call `get_endpoint` with method `get`, path `/api/v1/balance` in the CoinCircuit MCP for the full response schema.)*

- `currency` (optional) - `"NGN"` or your stablecoin (`"USDC"` or `"USDT"`). If omitted, returns your default currency balance.

Confirm `availableBalance` covers the amount you intend to swap before requesting a quotation.

### 2. Get an indicative estimate (optional)

Show the user roughly what they'll get before committing. This rate is **indicative only**, not locked.

**Endpoint:** `GET /api/v1/swap/estimate?fromCurrency={from}&toCurrency={to}&amount={amount}`
*(Call `get_endpoint` with method `get`, path `/api/v1/swap/estimate` in the CoinCircuit MCP for the full response schema.)*

**Query params:**
- `fromCurrency` - `"NGN"` or your stablecoin (`"USDC"` or `"USDT"`)
- `toCurrency` - the other side
- `amount` (string) - amount to swap, up to 2 decimal places, e.g. `"100.00"`

**Response (200):** `fromCurrency`, `toCurrency`, `sourceAmount`, `targetAmount`, `rate`.

Example: on-ramp 100,000 NGN into a stablecoin, or off-ramp 100.00 USDC/USDT into NGN.

### 3. Create a locked quotation

When the user commits, lock the rate.

**Endpoint:** `POST /api/v1/swap/quotation`
*(Call `get_endpoint` with method `post`, path `/api/v1/swap/quotation`, section `request` in the CoinCircuit MCP for the exact request body.)*

**Request body:**
```json
{
  "fromCurrency": "USDC",
  "toCurrency": "NGN",
  "amount": "100.00"
}
```

**Response (201):** Returns the quotation:
- `data.id` - the quotation ID (pass this to execute)
- `data.fromCurrency` / `data.toCurrency`
- `data.sourceAmount` / `data.targetAmount`
- `data.rate` - the locked rate
- `data.expiresAt` - **the quotation expires within seconds.** Execute promptly.
- `data.executed` - `false` until executed

*(Call `get_endpoint` with method `post`, path `/api/v1/swap/quotation`, section `success` in the CoinCircuit MCP for the full response schema.)*

### 4. Execute the swap

**Endpoint:** `POST /api/v1/swap/execute/{quotationId}`
*(Call `get_endpoint` with method `post`, path `/api/v1/swap/execute/{quotationId}` in the CoinCircuit MCP for the full schema.)*

No request body. Pass the `quotationId` from step 3 in the path. CoinCircuit atomically debits the source currency and credits the target currency at the locked rate.

**Response (200):** Returns the completed swap:
- `data.id` - swap ID
- `data.fromCurrency` / `data.toCurrency`
- `data.sourceAmount` / `data.targetAmount`
- `data.rate`
- `data.status` - `"completed"`
- `data.completedAt`

**Errors:** 400 (quotation expired, already used, or insufficient balance), 404 (quotation not found).

### 5. Withdraw fiat to a bank account (complete the off-ramp)

After swapping a stablecoin into NGN, move the NGN out to a bank account.

**Endpoint:** `POST /api/v1/payouts` with `method: "fiat"`
*(Call `get_endpoint` with method `post`, path `/api/v1/payouts` in the CoinCircuit MCP for the request body and the bank-account recipient setup.)*

Fiat payouts settle to the merchant's own registered bank account. Track them with `payout.success` / `payout.failed` webhooks.

### 6. Review swap history

- **List:** `GET /api/v1/swaps` (paginated)
- **Get one:** `GET /api/v1/swaps/{id}`

*(Call `get_endpoint` with method `get`, path `/api/v1/swaps` in the CoinCircuit MCP for pagination params and the response schema.)*

### Ramp Flow Summary

```
On-ramp:  Bank transfer -> NGN balance -> POST /swap/quotation (NGN -> USDC/USDT) -> POST /swap/execute -> stablecoin balance
Off-ramp: Stablecoin balance -> POST /swap/quotation (USDC/USDT -> NGN) -> POST /swap/execute -> NGN balance -> POST /payouts (fiat) -> bank
```

## Constraints

- Supported swap currencies are `NGN` and a stablecoin (`USDC` or `USDT`). `amount` is a **string** with up to 2 decimal places (e.g. `"100.00"`).
- The estimate is a preview only. The rate is locked when you create a quotation.
- **Quotations expire within seconds.** Create the quotation immediately before executing, and handle the "expired" error by re-quoting.
- A quotation can only be executed **once**. Re-executing a used quotation returns a 400.
- Show users the `targetAmount` from the quotation. That is the exact amount they receive at the locked rate.
- Always check `availableBalance` for the source currency before quoting.
