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
// Sell 10 USDC for COP
// 1. Get quote (network required!)
const quote = await axios.post(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/quotes`,
{
type: 'OFFRAMP',
originCurrencySymbol: 'USDC',
destinationCurrencySymbol: 'COP',
amountIn: 10, // 10 USDC
network: 'ETHEREUM' // Required for crypto quotes
},
{ headers: { 'Authorization': `Bearer ${token}` } }
);
console.log('Will receive:', quote.data.amountOut, 'COP'); // e.g., 39,500 COP
console.log('Quote valid for:', quote.data.validFor || '10-15', '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 confirmationComplete Payment Required: Unlike ONRAMP, OFFRAMP deals must be funded completely. Partial payments are not supported.
Step-by-Step Integration
Step 1: Get Quote
const quote = await axios.post(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/quotes`,
{
type: 'OFFRAMP',
originCurrencySymbol: 'USDC',
destinationCurrencySymbol: 'COP',
amountIn: 10,
network: 'ETHEREUM' // Required for crypto quotes
},
{ headers: { 'Authorization': `Bearer ${token}` } }
);
// Display to user
console.log('Selling:', quote.data.amountIn, 'USDC');
console.log('Will receive:', quote.data.amountOut, 'COP');
console.log('Exchange rate:', quote.data.exchangeRate);
console.log('Fee:', quote.data.koyweFee, 'COP');
console.log('Quote expires in:', quote.data.validFor || '10-15', 'seconds');Step 2: Create Deal
const deal = await axios.post(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/deals`,
{
type: 'OFFRAMP',
destinationAccountId: 'va_cop_12345', // Only need destination virtual account
quoteId: quote.data.id,
externalId: `offramp-${Date.now()}`
},
{ headers: { 'Authorization': `Bearer ${token}` } }
);
console.log('Deal created:', deal.data.id);
console.log('Status:', deal.data.status); // "PENDING"
console.log('Deposit address:', deal.data.depositAddress); // Where to send cryptoSimplified 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:
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.depositAddress);
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
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
Complete Example
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`,
{
type: 'OFFRAMP',
originCurrencySymbol: 'USDC',
destinationCurrencySymbol: 'COP',
amountIn: amount
},
{ headers: { 'Authorization': `Bearer ${token}` } }
);
console.log(`Selling ${amount} USDC for ${quote.data.amountOut} 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.