Koywe
On this page

Offramp - Sell Cryptocurrency

Convert cryptocurrency to fiat currency in your virtual account.

What is OFFRAMP?

OFFRAMP allows you to sell cryptocurrency and receive fiat funds in your virtual account.

Use cases:

  • Convert crypto holdings to fiat
  • Realize crypto gains
  • Prepare fiat for operations
  • Accept crypto payments and convert to fiat

Deals vs Orders

Important: OFFRAMP operations use the /deals endpoint, not /orders. A deal represents the intent to sell crypto and must be paid completely (no partial payments). The deal creates orders that execute the sale.

Key differences from ONRAMP:

  • Deal: The crypto sale intent (must be funded completely)
  • Order: The actual execution of the sale (created automatically by the deal)
  • No partial payments: OFFRAMP deals must be paid in full, unlike ONRAMP
  • Destination: Deals only need the destination virtual account

Quick Example

JavaScript
// Sell 10 USDC for COP
 
// 1. Get quote
const quote = await axios.post(
  `https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/quotes`,
  {
    orderType: 'OFFRAMP',
    executable: true,
    originCurrencySymbol: 'USDC',
    destinationCurrencySymbol: 'COP',
    amountIn: 10,  // 10 USDC
    network: 'ETHEREUM'  // Required for ONRAMP/OFFRAMP
  },
  { headers: { 'Authorization': `Bearer ${token}` } }
);
 
console.log('Will receive:', quote.data.finalAmountOut, 'COP'); // e.g., 39,500 COP
console.log('Quote valid for:', quote.data.validForSeconds, 'seconds');
 
// 2. Create deal (not order!)
const deal = await axios.post(
  `https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/deals`,
  {
    destinationAccountId: 'va_cop_12345',  // Your COP virtual account
    quoteId: quote.data.id
  },
  { headers: { 'Authorization': `Bearer ${token}` } }
);
 
console.log('Deal created:', deal.data.id);
console.log('Deal must be paid completely');
// Funds will be credited to COP virtual account after confirmation

Complete Payment Required: Unlike ONRAMP, OFFRAMP deals must be funded completely. Partial payments are not supported.


Step-by-Step Integration

Step 1: Get Quote

JavaScript
const quote = await axios.post(
  `https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/quotes`,
  {
    orderType: 'OFFRAMP',
    executable: true,
    originCurrencySymbol: 'USDC',
    destinationCurrencySymbol: 'COP',
    amountIn: 10,
    network: 'ETHEREUM'  // Required for ONRAMP/OFFRAMP
  },
  { headers: { 'Authorization': `Bearer ${token}` } }
);
 
// Display to user
console.log('Selling:', quote.data.finalAmountIn, 'USDC');
console.log('Will receive:', quote.data.finalAmountOut, 'COP');
console.log('Exchange rate:', quote.data.exchangeRate);
console.log('Fee:', quote.data.fee, 'COP');
console.log('Quote expires in:', quote.data.validForSeconds, 'seconds');

Step 2: Create Deal

JavaScript
const deal = await axios.post(
  `https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/deals`,
  {
    destinationAccountId: 'va_cop_12345',  // Only need destination virtual account
    quoteId: quote.data.id
  },
  { headers: { 'Authorization': `Bearer ${token}` } }
);
 
console.log('Deal created:', deal.data.id);
console.log('Status:', deal.data.status); // "PENDING"
console.log('Deposit address:', deal.data.cryptoDestinationWallet); // Where to send crypto

Simplified Request: Deals only need the destinationAccountId (virtual account) and quoteId. The crypto amount and currencies are already defined in the quote.

Step 3: Send Cryptocurrency

After creating the deal, send the cryptocurrency to the provided deposit address:

JavaScript
const dealDetails = await axios.get(
  `https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/deals/${deal.data.id}`,
  { headers: { 'Authorization': `Bearer ${token}` } }
);
 
console.log('Send crypto to:', dealDetails.data.cryptoDestinationWallet);
console.log('Amount to send:', dealDetails.data.amountIn, dealDetails.data.originCurrencySymbol);
console.log('Network:', dealDetails.data.network);
console.log('Must send complete amount - partial payments not allowed');

Step 4: Wait for Confirmation

JavaScript
app.post('/webhooks/koywe', (req, res) => {
  const event = JSON.parse(req.body);
  
  if (event.type === 'order.paid' && event.data.type === 'OFFRAMP') {
    console.log('Crypto received and confirmed!');
  }
  
  if (event.type === 'order.completed' && event.data.type === 'OFFRAMP') {
    console.log('Fiat credited to virtual account!');
    console.log('Amount:', event.data.amountOut, event.data.destinationCurrencySymbol);
  }
  
  res.status(200).send('OK');
});

Order Flow

Drawing diagram…

Complete Example

JavaScript
async function sellUSDC(amount) {
  try {
    const token = await authenticate();
    
    // 1. Get quote
    const quote = await axios.post(
      `https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/quotes`,
      {
        orderType: 'OFFRAMP',
        executable: true,
        originCurrencySymbol: 'USDC',
        destinationCurrencySymbol: 'COP',
        amountIn: amount,
        network: 'ETHEREUM'  // Required for ONRAMP/OFFRAMP
      },
      { headers: { 'Authorization': `Bearer ${token}` } }
    );
 
    console.log(`Selling ${amount} USDC for ${quote.data.finalAmountOut} COP`);
    console.log(`Rate: 1 USDC = ${quote.data.exchangeRate} COP`);
    
    // 2. Create offramp order
    const order = await axios.post(
      `https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/orders`,
      {
        type: 'OFFRAMP',
        originCurrencySymbol: 'USDC',
        destinationCurrencySymbol: 'COP',
        amountIn: amount,
        quoteId: quote.data.id
      },
      { headers: { 'Authorization': `Bearer ${token}` } }
    );
    
    console.log('βœ“ Offramp order created:', order.data.id);
    console.log('πŸ“ Send USDC to:', order.data.depositAddress);
    console.log('πŸ’° Amount:', order.data.amountIn, 'USDC');
    console.log('🌐 Network:', order.data.network || 'Ethereum');
    
    return {
      orderId: order.data.id,
      depositAddress: order.data.depositAddress,
      amount: order.data.amountIn,
      currency: order.data.originCurrencySymbol
    };
    
  } catch (error) {
    console.error('Error:', error.response?.data || error.message);
    throw error;
  }
}
 
// Usage
const offramp = await sellUSDC(10);
console.log('Send your USDC to the deposit address above');

Important Notes

Blockchain Confirmations: OFFRAMP orders require blockchain confirmations. Settlement time varies by network:

  • Ethereum: 12-15 minutes (12 confirmations)
  • Polygon: 2-5 minutes (128 confirmations)
  • BSC: 3-5 minutes (15 confirmations)
  • Bitcoin: 30-60 minutes (3 confirmations)

One-time Address: Each OFFRAMP order generates a unique deposit address. Don’t reuse addresses from previous orders.


Next Steps