Onramp - Buy Cryptocurrency
Convert fiat currency to cryptocurrency using your virtual balance.
What is ONRAMP?
ONRAMP allows you to purchase cryptocurrency using fiat funds from your virtual account.
Supported cryptocurrencies: see Supported Networks below for the exact symbol/network pairs the API accepts.
Deals vs Orders
Important: ONRAMP operations use the /deals endpoint, not /orders. A deal represents the intent to buy crypto and can be paid in full or partially. Each payment creates one or more orders that execute the purchase.
Key differences:
- Deal: The crypto purchase intent (can be partially funded)
- Order: The actual execution of the purchase (created automatically by the deal)
- Partial payments: You can pay a deal in multiple installments for ONRAMP
- Destination: Deals only need the destination wallet/account
Automatic Payment Execution
Balance Required: By default, you need sufficient balance in your virtual account to close an ONRAMP deal. ONRAMP payments execute automatically when there’s a credit to your currency balance.
How it works:
- Create an ONRAMP deal for X amount of crypto
- Deal requires Y fiat in your virtual account
- When your virtual account receives funds (PAYIN, etc.), the deal automatically executes
- Orders are created and crypto is purchased
Pre-approved Merchants:
- Some merchants can operate deals without requiring upfront balance
- This allows creating deals before funds are available
- Contact Koywe to request pre-approval for this feature
Quick Example
// Buy USDC with COP
// 1. Get quote
const quote = await axios.post(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/quotes`,
{
orderType: 'ONRAMP',
executable: true,
originCurrencySymbol: 'COP',
destinationCurrencySymbol: 'USDC',
amountIn: 50000, // 50,000 COP
network: 'ETHEREUM' // Required for ONRAMP/OFFRAMP
},
{ headers: { 'Authorization': `Bearer ${token}` } }
);
console.log('Will receive:', quote.data.finalAmountOut, 'USDC'); // e.g., 12.34 USDC
console.log('Fee:', quote.data.fee, '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`,
{
// Id of your CRYPTO account in K3 — not a wallet address
destinationAccountId: 'acc_77a80cf9-496c-4d72-9c33-fca3c8d5bcfe',
quoteId: quote.data.id
},
{ headers: { 'Authorization': `Bearer ${token}` } }
);
console.log('Deal created:', deal.data.id);
console.log('Deal will create orders automatically as it executes');
// Monitor deal.status: PENDING → PROCESSING → COMPLETEDStep-by-Step Integration
Step 1: Get Your Crypto Destination Account
ONRAMP deals deliver crypto to a K3 account of kind: "CRYPTO". What the deal needs is that account’s id (acc_…), so look it up first:
// Find your CRYPTO account for the currency and network you're buying
const accounts = await axios.get(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/search`,
{
params: { kind: 'CRYPTO', currencySymbol: 'USDC', network: 'ETHEREUM' },
headers: { 'Authorization': `Bearer ${token}` }
}
);
const cryptoAccount = accounts.data[0];
if (!cryptoAccount) {
throw new Error('No USDC account on ETHEREUM — register or provision one first');
}
console.log('Destination account id:', cryptoAccount.id); // acc_… — this is what the deal takes
console.log('Wallet address:', cryptoAccount.address); // 0x… — informational only
console.log('Network:', cryptoAccount.network);Pass the id, not the address: destinationAccountId is a K3 account id (acc_…). A wallet address (0x…) is not a valid value.
No crypto account yet? Register your own wallet as an external crypto account with POST /accounts and kind: "CRYPTO" — see Merchant External Accounts. Koywe-managed embedded wallets are provisioned with a passkey instead — see Passkeys & Approvals.
Step 2: Check Fiat Balance
Balance Required: Unless your merchant is pre-approved, you need sufficient balance to close the deal. The deal will execute automatically when funds are available.
const balances = await axios.get(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/balances`,
{ headers: { 'Authorization': `Bearer ${token}` } }
);
const copBalance = balances.data.find(b => b.currencySymbol === 'COP');
if (copBalance.availableBalance < 50000) {
console.log('Insufficient balance. Deal will execute when funds arrive.');
// For pre-approved merchants, you can continue
// For others, you may need to wait for PAYIN to credit the account
}Step 3: Get Quote
const quote = await axios.post(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/quotes`,
{
orderType: 'ONRAMP',
executable: true,
originCurrencySymbol: 'COP',
destinationCurrencySymbol: 'USDC',
amountIn: 50000,
network: 'ETHEREUM' // Required for ONRAMP/OFFRAMP
},
{ headers: { 'Authorization': `Bearer ${token}` } }
);
// Display to user
console.log('Exchange rate:', quote.data.exchangeRate);
console.log('Will receive:', quote.data.finalAmountOut, 'USDC');
console.log('Fee:', quote.data.fee, 'COP');
console.log('Total cost:', quote.data.finalAmountIn, 'COP');
console.log('Quote expires in:', quote.data.validForSeconds, 'seconds');Step 4: Create Deal
const deal = await axios.post(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/deals`,
{
destinationAccountId: cryptoAccount.id, // Only need destination (from Step 1)
quoteId: quote.data.id
},
{ headers: { 'Authorization': `Bearer ${token}` } }
);
console.log('Deal created:', deal.data.id);
console.log('Status:', deal.data.status); // "PENDING"
console.log('Deals can be paid in full or partially');What happens next: The deal will automatically create orders as payments are processed. You can fund the deal in one payment or multiple partial payments.
Step 5: Monitor Deal and Orders
// Via webhooks (recommended)
app.post('/webhooks/koywe', (req, res) => {
const event = JSON.parse(req.body);
// Deal status updates
if (event.type === 'deal.completed' && event.data.type === 'ONRAMP') {
console.log('Deal completed!');
console.log('Deal ID:', event.data.id);
}
// Orders created by the deal
if (event.type === 'order.completed' && event.data.type === 'ONRAMP') {
console.log('Crypto received!');
console.log('Order ID:', event.data.id);
console.log('Amount:', event.data.amountOut, event.data.destinationCurrencySymbol);
}
res.status(200).send('OK');
});// Or poll deal status
async function checkDealStatus(dealId) {
const deal = await axios.get(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/deals/${dealId}`,
{ headers: { 'Authorization': `Bearer ${token}` } }
);
console.log('Deal status:', deal.data.status);
console.log('Orders created:', deal.data.orders); // Array of order IDs
return deal.data;
}Supported Networks
| Network | Chain | Currencies |
|---|---|---|
ETHEREUM | Ethereum | ETH · USDC · USDT |
POLYGON | Polygon | MATIC · USDC · USDT |
SOLANA | Solana | SOL · USDC · USDT |
BASE | Base | ETH · USDC · USDT · EURC |
ALGORAND | Algorand | USDC · USDT |
TRON | Tron | TRX · USDT |
BSC | BNB Smart Chain | USDT |
BITCOIN | Bitcoin | BTC |
Only these pairs are valid. Any other symbol/network combination is rejected by the API.
Network Selection: Pass network on the quote, and make sure your destination crypto account is registered on that same network.
Partial Payments (ONRAMP Only)
Unique to ONRAMP: Unlike OFFRAMP (which must be paid completely), ONRAMP deals can be paid in multiple partial payments. Each partial payment creates an order that purchases the corresponding amount of crypto.
How Partial Payments Work
Example: Partial Payment Deal
// Create a deal for 100 USDC
const quote = await axios.post(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/quotes`,
{
orderType: 'ONRAMP',
executable: true,
originCurrencySymbol: 'COP',
destinationCurrencySymbol: 'USDC',
amountIn: 400000, // 400,000 COP for ~100 USDC
network: 'ETHEREUM' // Required for ONRAMP/OFFRAMP
},
{ headers: { 'Authorization': `Bearer ${token}` } }
);
const deal = await axios.post(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/deals`,
{
destinationAccountId: 'acc_77a80cf9-496c-4d72-9c33-fca3c8d5bcfe', // Your CRYPTO account id
quoteId: quote.data.id
},
{ headers: { 'Authorization': `Bearer ${token}` } }
);
console.log('Deal created for 100 USDC');
console.log('You can now pay this deal in full or partially');
console.log('Each payment will create an order and purchase crypto proportionally');
// Payment 1: Pay 50% now (200,000 COP → ~50 USDC)
// Payment 2: Pay 50% later (200,000 COP → ~50 USDC)
// Result: 2 orders created, 100 USDC total receivedUse Case: Partial payments are useful for:
- Dollar-cost averaging (DCA) strategies
- Staged purchases over time
- Managing cash flow while building crypto position
- Allowing customers to pay in installments
Complete Example
async function buyUSDC(amount) {
try {
const token = await authenticate();
// 1. Check COP balance
const balances = await getBalances(token, orgId, merchantId);
const copBalance = balances.find(b => b.currencySymbol === 'COP');
if (copBalance.availableBalance < amount) {
throw new Error('Insufficient COP balance');
}
// 2. Find the CRYPTO account that will receive the crypto
const accounts = await axios.get(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/accounts/search`,
{
params: { kind: 'CRYPTO', currencySymbol: 'USDC', network: 'ETHEREUM' },
headers: { 'Authorization': `Bearer ${token}` }
}
);
const cryptoAccount = accounts.data[0];
if (!cryptoAccount) {
throw new Error('No USDC account on ETHEREUM — register or provision one first');
}
// 3. Get quote
const quote = await axios.post(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/quotes`,
{
orderType: 'ONRAMP',
executable: true,
originCurrencySymbol: 'COP',
destinationCurrencySymbol: 'USDC',
amountIn: amount,
network: 'ETHEREUM' // Required for ONRAMP/OFFRAMP
},
{ headers: { 'Authorization': `Bearer ${token}` } }
);
console.log(`Converting ${amount} COP to ${quote.data.finalAmountOut} USDC`);
console.log(`Rate: 1 USDC = ${quote.data.exchangeRate} COP`);
// 4. Create deal
const deal = await axios.post(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/deals`,
{
destinationAccountId: cryptoAccount.id, // Account id, not the address
quoteId: quote.data.id
},
{ headers: { 'Authorization': `Bearer ${token}` } }
);
console.log('USDC purchase deal created:', deal.data.id);
console.log('Deal will create orders as it executes');
return deal.data;
} catch (error) {
console.error('Error:', error.response?.data || error.message);
throw error;
}
}
// Usage
await buyUSDC(50000); // Buy USDC with 50,000 COP