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

# Custom Stablecoins on Monad with Brale

Deploy regulated, fully-backed USD stablecoins on Monad and integrate them into your application with onramps, offramps, and custody.

## Overview

Monad's high-performance EVM, with 10,000+ tx/s and sub-second time-to-finality, makes it well-suited for stablecoin-powered applications. Brale lets businesses create their own stablecoins and then access them programmatically through a single API for money movements.

## What You'll Build

By the end of this guide, you'll have:

* A custom stablecoin launched on Monad
* API credentials for programmatic control
* Working integrations for onramps, transfers, swaps, and offramps

## Why Custom Stablecoins?

| Use Case              | Benefit                                                              |
| --------------------- | -------------------------------------------------------------------- |
| Branded experience    | Your token, your identity—build user trust                           |
| Direct fiat rails     | Connect to ACH, wire, and RTP through a single orchestration layer   |
| Cross-chain liquidity | Move value across supported chains through a unified transfers model |
| Compliance built-in   | Brale handles the regulated issuance and orchestration layer         |

***

## Prerequisites

Before starting, ensure you have:

* A registered business entity for KYB verification
* A [Brale account](https://app.brale.xyz/)
* Monad network and wallet access:
  * [Mainnet network info](https://docs.monad.xyz/developer-essentials/network-information)
  * [Testnet network info](https://docs.monad.xyz/developer-essentials/testnets)
  * [Add Monad to your wallet](https://docs.monad.xyz/guides/add-monad-to-wallet)

## Choose Your Environment

Use Brale testnet while developing and switch to mainnet for production. In testnet, use `monad_testnet` as the `transfer_type` and in mainnet, use `monad`. Brale's testnet supports testnet networks only and skips the real fiat leg on mint and redemption flows.

***

## Part 1: Launch Your Stablecoin in Brale

Stablecoin issuance is a dashboard workflow. API integration begins after your stablecoin has been launched. Once issued, the stablecoin is available via the API.

### Step 1: Complete Business Verification

1. Log in to the Brale Dashboard
2. Complete KYB (Know Your Business) verification:
   * Business name and EIN
   * Beneficial ownership information

### Step 2: Launch Your Stablecoin

In the Brale Dashboard, create your stablecoin and configure:

* **Name:** Your stablecoin's display name (for example, Acme Dollar)
* **Symbol:** Token ticker (for example, ACME)
* **Chains:** Select Monad
* **Branding:** Add your token logo

Then fund it via Wire, ACH, or USDC.

Once your stablecoin is live, continue with the API setup below.

***

## Part 2: Integrate with the Brale API

Brale's API uses OAuth 2.0 client credentials, environment-specific applications, and `address_id` values as the source/destination primitive for transfers.

### Step 1: Create API Credentials

1. Sign in to your Brale account
2. Navigate to **Settings → API**
3. Click **Create Application**
4. Give the application a name and choose **Mainnet** or **Testnet**
5. Copy the generated `CLIENT_ID` and `CLIENT_SECRET`

Brale API applications are environment-specific, and the same application credentials can be used for direct API access and the hosted Brale API MCP server.

### Step 2: Authenticate

Exchange your credentials for a bearer token:

```bash theme={null}
export CLIENT_ID="your_client_id"
export CLIENT_SECRET="your_client_secret"

CLIENT_CREDENTIALS=$(
  printf "%s:%s" "${CLIENT_ID}" "${CLIENT_SECRET}" | base64 | tr -d '\n'
)

curl --request POST \
  --url "https://auth.brale.xyz/oauth2/token" \
  --header "Authorization: Basic ${CLIENT_CREDENTIALS}" \
  --header "Content-Type: application/x-www-form-urlencoded" \
  --data grant_type=client_credentials
```

**Response**

```json theme={null}
{
  "access_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 3600
}
```

Use the returned token in subsequent requests:

```bash theme={null}
export AUTH_TOKEN="your_access_token"
```

### Step 3: Set Your Working Variables

```bash theme={null}
export ACCOUNT_ID="your_account_id"
export TOKEN_SYMBOL="ACME"

# Use testnet while developing
export MONAD_TRANSFER_TYPE="monad_testnet"

# Switch to mainnet for production
# export MONAD_TRANSFER_TYPE="monad"
```

### Step 4: Retrieve Your `account_id`

List your accounts and identify the account you want to operate on:

```bash theme={null}
curl --request GET \
  --url "https://api.brale.xyz/accounts" \
  --header "Authorization: Bearer ${AUTH_TOKEN}"
```

### Step 5: Get Your Internal Monad `address_id`

Brale automatically generates internal custodial addresses on supported chains for onboarded accounts. Retrieve the internal Monad address you want to use for custodial flows:

```bash theme={null}
curl --request GET \
  --url "https://api.brale.xyz/accounts/${ACCOUNT_ID}/addresses?type=internal&transfer_type=${MONAD_TRANSFER_TYPE}" \
  --header "Authorization: Bearer ${AUTH_TOKEN}"
```

Store the returned internal Monad `address_id`:

```bash theme={null}
export MONAD_ADDRESS_ID="your_internal_monad_address_id"
```

### Step 6: Register an External Monad Wallet (Optional)

If you want to send to or receive from a self-custody Monad wallet, register it as an external address first. In Brale, addresses can be `type=internal` or `type=external`, and both are represented by `address_id` values used in transfers.

```bash theme={null}
curl --request POST \
  --url "https://api.brale.xyz/accounts/${ACCOUNT_ID}/addresses/external" \
  --header "Authorization: Bearer ${AUTH_TOKEN}" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: $(uuidgen)" \
  --data '{
    "name": "User Monad Wallet",
    "address": "0x1234567890abcdef1234567890abcdef12345678",
    "transfer_types": ["'"${MONAD_TRANSFER_TYPE}"'"]
  }'
```

**Response**

```json theme={null}
{
  "id": "2VcUIIsgARwVbEGlIYbhg6fGG57"
}
```

Store the returned `id` as the wallet's Brale `address_id`:

```bash theme={null}
export EXTERNAL_MONAD_ADDRESS_ID="your_external_monad_address_id"
```

***

## Alternative: Brale API MCP Server

Brale offers a hosted API MCP server for live API access from MCP-compatible clients. The remote server URL is `https://mcp.brale.xyz/`.

### Setup for Claude Desktop

1. Open **Settings → Connectors**
2. Click **Add custom connector**
3. Enter the remote MCP server URL: `https://mcp.brale.xyz/`
4. Open **Advanced settings** and enter your OAuth Client ID and Client Secret
5. Save the connector

Once added, enable it from the Search and Tools menu in chat.

<Info>
  Custom connectors are available on Pro, Max, Team, and Enterprise plans.
</Info>

### Setup for Cursor

Add a server entry in **Settings → MCP**:

```json theme={null}
{
  "name": "Brale API MCP",
  "url": "https://mcp.brale.xyz/",
  "env": {
    "CLIENT_ID": "your_client_id",
    "CLIENT_SECRET": "your_client_secret"
  }
}
```

### Setup for Windsurf

Edit `~/.codeium/windsurf/mcp_config.json`:

```json theme={null}
{
  "mcpServers": {
    "Brale API MCP": {
      "url": "https://mcp.brale.xyz/",
      "env": {
        "CLIENT_ID": "your_client_id",
        "CLIENT_SECRET": "your_client_secret"
      }
    }
  }
}
```

Restart Windsurf after saving.

***

## Move Value with Transfers

All stablecoin movement is handled through the Transfers API. Every transfer is scoped to an `account_id`, references `address_id` values where applicable, and uses `transfer_type` plus `value_type` to define the rail/chain and asset being moved.

### Base URL

```
https://api.brale.xyz/accounts/${ACCOUNT_ID}/transfers
```

### Required Headers

```
Authorization: Bearer ${AUTH_TOKEN}
Content-Type: application/json
Idempotency-Key: $(uuidgen)
```

<Tip>
  Always include a fresh `Idempotency-Key` on create requests.
</Tip>

***

## Onramps: Fiat to Stablecoin

Convert USD to your stablecoin on Monad.

### Option A: Wire Onramp

```bash theme={null}
curl --request POST \
  --url "https://api.brale.xyz/accounts/${ACCOUNT_ID}/transfers" \
  --header "Authorization: Bearer ${AUTH_TOKEN}" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: $(uuidgen)" \
  --data '{
    "amount": {
      "value": "1000.00",
      "currency": "USD"
    },
    "source": {
      "value_type": "usd",
      "transfer_type": "wire"
    },
    "destination": {
      "address_id": "'"${MONAD_ADDRESS_ID}"'",
      "value_type": "'"${TOKEN_SYMBOL}"'",
      "transfer_type": "'"${MONAD_TRANSFER_TYPE}"'"
    }
  }'
```

### Option B: ACH Onramp

If you are funding from a linked bank account, use an ACH funding address and mint to your Monad destination address:

```bash theme={null}
export FUNDING_ADDRESS_ID="your_ach_funding_address_id"

curl --request POST \
  --url "https://api.brale.xyz/accounts/${ACCOUNT_ID}/transfers" \
  --header "Authorization: Bearer ${AUTH_TOKEN}" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: $(uuidgen)" \
  --data '{
    "amount": {
      "value": "1000.00",
      "currency": "USD"
    },
    "source": {
      "address_id": "'"${FUNDING_ADDRESS_ID}"'",
      "value_type": "usd",
      "transfer_type": "ach_debit"
    },
    "destination": {
      "address_id": "'"${MONAD_ADDRESS_ID}"'",
      "value_type": "'"${TOKEN_SYMBOL}"'",
      "transfer_type": "'"${MONAD_TRANSFER_TYPE}"'"
    }
  }'
```

### Option C: Automated Onramps

For recurring flows, create an Automation that mints stablecoins automatically when USD arrives:

1. In the Dashboard, navigate to **Automations**
2. Create an automation that listens for inbound ACH or wire funding
3. Set the destination to your Monad address
4. Save the automation

***

## Transfers: Move Stablecoins

Transfer your stablecoin between addresses on Monad or across chains.

### On-Chain Transfer (Monad)

```bash theme={null}
export SOURCE_ADDRESS_ID="your_source_monad_address_id"
export DESTINATION_ADDRESS_ID="your_destination_monad_address_id"

curl --request POST \
  --url "https://api.brale.xyz/accounts/${ACCOUNT_ID}/transfers" \
  --header "Authorization: Bearer ${AUTH_TOKEN}" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: $(uuidgen)" \
  --data '{
    "amount": {
      "value": "500.00",
      "currency": "USD"
    },
    "source": {
      "address_id": "'"${SOURCE_ADDRESS_ID}"'",
      "value_type": "'"${TOKEN_SYMBOL}"'",
      "transfer_type": "'"${MONAD_TRANSFER_TYPE}"'"
    },
    "destination": {
      "address_id": "'"${DESTINATION_ADDRESS_ID}"'",
      "value_type": "'"${TOKEN_SYMBOL}"'",
      "transfer_type": "'"${MONAD_TRANSFER_TYPE}"'"
    }
  }'
```

### Cross-Chain Transfer

Move your stablecoin from Monad to another supported chain:

```bash theme={null}
export BASE_ADDRESS_ID="your_base_address_id"

curl --request POST \
  --url "https://api.brale.xyz/accounts/${ACCOUNT_ID}/transfers" \
  --header "Authorization: Bearer ${AUTH_TOKEN}" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: $(uuidgen)" \
  --data '{
    "amount": {
      "value": "500.00",
      "currency": "USD"
    },
    "source": {
      "address_id": "'"${MONAD_ADDRESS_ID}"'",
      "value_type": "'"${TOKEN_SYMBOL}"'",
      "transfer_type": "'"${MONAD_TRANSFER_TYPE}"'"
    },
    "destination": {
      "address_id": "'"${BASE_ADDRESS_ID}"'",
      "value_type": "'"${TOKEN_SYMBOL}"'",
      "transfer_type": "base"
    }
  }'
```

***

## Swaps: Exchange Stablecoins

Swap between supported stablecoins at 1:1 with no slippage.

<Info>
  Confirm the specific `value_type` and `transfer_type` combination you plan to use before production.
</Info>

### Example: Swap Your Token for USDC

```bash theme={null}
export USDC_DESTINATION_ADDRESS_ID="your_usdc_destination_address_id"

curl --request POST \
  --url "https://api.brale.xyz/accounts/${ACCOUNT_ID}/transfers" \
  --header "Authorization: Bearer ${AUTH_TOKEN}" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: $(uuidgen)" \
  --data '{
    "amount": {
      "value": "250.00",
      "currency": "USD"
    },
    "source": {
      "address_id": "'"${MONAD_ADDRESS_ID}"'",
      "value_type": "'"${TOKEN_SYMBOL}"'",
      "transfer_type": "'"${MONAD_TRANSFER_TYPE}"'"
    },
    "destination": {
      "address_id": "'"${USDC_DESTINATION_ADDRESS_ID}"'",
      "value_type": "USDC",
      "transfer_type": "base"
    }
  }'
```

***

## Offramps: Stablecoin to Fiat

Convert your stablecoin back to USD via wire or ACH.

### Offramp to Wire

```bash theme={null}
export USD_DESTINATION_ADDRESS_ID="your_wire_destination_address_id"

curl --request POST \
  --url "https://api.brale.xyz/accounts/${ACCOUNT_ID}/transfers" \
  --header "Authorization: Bearer ${AUTH_TOKEN}" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: $(uuidgen)" \
  --data '{
    "amount": {
      "value": "1000.00",
      "currency": "USD"
    },
    "source": {
      "address_id": "'"${MONAD_ADDRESS_ID}"'",
      "value_type": "'"${TOKEN_SYMBOL}"'",
      "transfer_type": "'"${MONAD_TRANSFER_TYPE}"'"
    },
    "destination": {
      "address_id": "'"${USD_DESTINATION_ADDRESS_ID}"'",
      "value_type": "usd",
      "transfer_type": "wire"
    }
  }'
```

### Offramp to ACH

For ACH payouts, use `ach_credit` or `same_day_ach_credit` on the destination address instead of `wire`.

***

## Monitoring Transfers

Check transfer status by querying the transfer ID:

```bash theme={null}
export TRANSFER_ID="your_transfer_id"

curl --request GET \
  --url "https://api.brale.xyz/accounts/${ACCOUNT_ID}/transfers/${TRANSFER_ID}" \
  --header "Authorization: Bearer ${AUTH_TOKEN}"
```

### Transfer States

| Status       | Description                                                  |
| ------------ | ------------------------------------------------------------ |
| `pending`    | Transfer submitted but not yet in progress                   |
| `processing` | Transfer is in progress                                      |
| `complete`   | Transfer finalized and funds have arrived at the destination |
| `canceled`   | Transfer has been canceled                                   |
| `failed`     | Transfer could not be completed                              |

***

## Best Practices

### Security

* Store API credentials in environment variables or a secrets manager
* Use a fresh idempotency key for each new transfer request
* Refresh bearer tokens when they expire

### Testing

* Use testnet credentials during development
* Use `monad_testnet` while testing and `monad` in production
* Do not mix testnet credentials/resources with mainnet flows

### Addressing

* Use internal addresses for Brale-custodied wallets
* Register self-custody Monad wallets as external addresses before using them in transfers
* Store returned `address_id` values and reuse them across workflows

***

## Next Steps

* Explore the [Brale docs](https://docs.brale.xyz/)
* Review the [Brale API MCP guide](https://docs.brale.xyz/mcp/api)
* Confirm [supported transfer types and value types](https://docs.brale.xyz/coverage/transfer-types) before shipping production flows
