Skip to main content
This guide walks through a complete OFFRAMP flow: converting USDC on Gnosis Chain to USD.

Overview

1

Create Customer

Get access token for API calls
2

Get Indicative Quote

Compare pricing across providers
3

Get Requirements

Fetch field schemas for the currency pair
4

Create Intent

Submit the OFFRAMP intent
5

Handle Compliance

Complete KYC if required
6

Execute Transaction

Trigger the transaction
7

Send Crypto

User sends crypto to deposit address
8

Monitor & Complete

Track status until completion

Prerequisites

  • Gnosis Ramp API credentials (Getting Started)
  • A connected ramp provider that supports USDC_GNO → USD

Step 1: Create Customer

For faster compliance with KYC sharing, use external authentication instead.

API Call

POST /v1/customers

Sample Request Body

{
  "id": "user-12345"
}

Sample Response

{
  "id": "user-12345",
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "createdAt": "2026-03-29T10:00:00.000Z",
  "updatedAt": "2026-03-29T10:00:00.000Z"
}

Step 2: Get Indicative Quote

Before creating an intent, fetch indicative quotes to show users pricing options.

API Call

GET /v1/intent/quote

Sample Request

GET /v1/intent/quote?srcCurrencyCode=USDC_GNO&destCurrencyCode=USD&srcAmount=100.000000&countryCode=US

Sample Response

{
  "quotes": [
    {
      "providerId": "bridge",
      "type": "OFFRAMP",
      "rail": "ACH",
      "hasIndicativePrice": true,
      "destAmount": "98.50",
      "exchangeRate": "0.9850",
      "fees": {
        "currencyCode": "USD",
        "totalFee": "1.50",
        "networkFee": "0.50",
        "processingFee": "0.75",
        "partnerFee": "0.25"
      }
    }
  ]
}
Quotes are non-binding estimates. The actual rate is determined at the time of settlement. See Getting a Quote for details.

Step 3: Get Requirements

API Call

GET /v1/intent/requirements

Sample Request

GET /v1/intent/requirements?srcCurrencyCode=USDC_GNO&destCurrencyCode=USD

Sample Response

{
  "src": {
    "currencyCode": "USDC_GNO",
    "schema": {
      "type": "object",
      "required": ["address", "currency"],
      "properties": {
        "address": { "pattern": "^0x[a-fA-F0-9]{40}$" },
        "currency": { "const": "USDC_GNO" }
      }
    }
  },
  "dest": {
    "currencyCode": "USD",
    "schema": {
      "type": "object",
      "required": ["countryCode", "currency", "rail"],
      "properties": {
        "countryCode": { "const": "US" },
        "currency": { "const": "USD" },
        "rail": { "type": "string", "enum": ["ACH", "WIRE"] }
      }
    }
  }
}
For OFFRAMP, the destination schema includes bank account fields.

Step 4: Create Intent

API Call

POST /v1/intent

Sample Request Body

{
  "src": {
    "currencyCode": "USDC_GNO",
    "details": {
      "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f..."
    }
  },
  "dest": {
    "currencyCode": "USD",
    "details": {
      "countryCode": "US",
      "rail": "ACH"
    }
  },
  "srcAmount": "100.000000",
  "autoExecute": true,
  "onboardingRedirectUrl": "https://yourapp.com/ramp/callback"
}
For OFFRAMP, use crypto decimal precision for srcAmount. USDC uses 6 decimals: "100.000000" not "100.00".

Sample Response

{
  "intent": {
    "id": "int_abc123def456",
    "status": "CREATED",
    "type": "OFFRAMP",
    "src": {
      "type": "CRYPTO_ADDRESS",
      "currency": "USDC_GNO",
      "details": {
        "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f..."
      }
    },
    "dest": {
      "type": "BANK_ACCOUNT",
      "currency": "USD",
      "details": {
        "countryCode": "US",
        "rail": "ACH"
      }
    },
    "srcAmount": "100.000000",
    "provider": "bridge",
    "autoExecute": true
  },
  "onboardingUrl": "https://onboarding.ramp.gnosis.io/session/abc123",
  "transaction": null
}

Step 5: Handle Compliance

Same as ONRAMP — show the compliance iframe if onboardingUrl is present:
if (onboardingUrl) {
  const iframe = document.createElement('iframe');
  iframe.src = onboardingUrl;
  iframe.style.cssText = 'width:100%;height:600px;border:none;';
  iframe.allow = 'camera';
  document.getElementById('onboarding-container').appendChild(iframe);

  window.addEventListener('message', (event) => {
    if (!event.origin.includes('ramp.gnosis.io')) return;
    if (event.data.type === 'INTENT_COMPLETED') {
      iframe.remove();
    }
  });
}

Step 6: Execute Transaction

API Call

POST /v1/intent/{intentId}/transaction

Sample Response

{
  "id": "txn_xyz789",
  "status": "PENDING",
  "depositInstructions": {
    "context": [
      {
        "type": "CRYPTO",
        "instructions": {
          "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f...",
          "network": "gnosis"
        }
      }
    ]
  }
}

Step 7: Display Crypto Deposit Instructions

For OFFRAMP, the user sends crypto instead of fiat:
// Get the crypto deposit instructions
const cryptoInstructions = depositInstructions.context.find(c => c.type === 'CRYPTO');

// Display to user
console.log(`
  Send ${intent.srcAmount} USDC to:

  Address: ${cryptoInstructions.instructions.address}
  Network: Gnosis Chain

  Make sure you're sending on the correct network!
`);

Example UI

+------------------------------------------+
| Send Your USDC                           |
|                                          |
| Amount: 100.000000 USDC                  |
| Network: Gnosis Chain                    |
|                                          |
| Send to:                                 |
| 0x742d35Cc6634C0532925a3b844Bc9e...     |
|                                          |
| [Copy Address]                           |
|                                          |
| Only send USDC on Gnosis Chain.          |
| Sending other tokens or using the        |
| wrong network may result in loss.        |
+------------------------------------------+

Step 8: Monitor Completion

API Call

GET /v1/intent/{intentId}/transaction

Sample Response

{
  "id": "txn_xyz789",
  "status": "SUCCESS",
  "srcAmount": "100.000000",
  "destAmount": "98.50",
  "completedAt": "2026-03-29T12:00:00.000Z"
}
Poll the endpoint until status is SUCCESS, FAILED, or CANCELLED.

Complete Example

async function offramp(userId, walletAddress, amountUsdc) {
  // 1. Create customer
  const credentials = btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
  const customer = await fetch('https://api.ramp.gnosis.io/v1/customers', {
    method: 'POST',
    headers: {
      'Authorization': `Basic ${credentials}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ id: userId })
  }).then(r => r.json());

  const accessToken = customer.accessToken;

  // 2. Create intent (note: 6 decimals for USDC)
  const { intent, onboardingUrl } = await fetch(
    'https://api.ramp.gnosis.io/v1/intent',
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        src: {
          currencyCode: 'USDC_GNO',
          details: { address: walletAddress }
        },
        dest: {
          currencyCode: 'USD',
          details: { countryCode: 'US', rail: 'ACH' }
        },
        srcAmount: amountUsdc.toFixed(6),  // 6 decimals!
        autoExecute: true
      })
    }
  ).then(r => r.json());

  // 3. Handle compliance if needed
  if (onboardingUrl) {
    await showComplianceIframe(onboardingUrl);
  }

  // 4. Get crypto deposit instructions
  const txn = await fetch(
    `https://api.ramp.gnosis.io/v1/intent/${intent.id}/transaction`,
    { headers: { 'Authorization': `Bearer ${accessToken}` } }
  ).then(r => r.json());

  const cryptoInstructions = txn.context.find(c => c.type === 'CRYPTO');

  return {
    intentId: intent.id,
    sendTo: cryptoInstructions.instructions.address,
    amount: intent.srcAmount,
    network: 'Gnosis Chain'
  };
}

Next Steps

ONRAMP Guide

Convert fiat to crypto.

Webhooks

Get real-time status updates.