Skip to main content

What is a Quotation?

A Quotation is a price quote for converting between currencies. It locks in an exchange rate for 30 seconds, allowing users to see exactly how much they’ll receive before committing to a transaction.
Quotations are required before creating any ramp. They ensure price transparency and protect against rate fluctuations.

How Quotations Work

1

Request Quote

Specify currencies, amount, and payment methods
2

Receive Rate

Get locked-in rate valid for 30 seconds
3

Show to User

Display exact amounts user will send/receive
4

Create Ramp

Use quotation ID to execute transaction at quoted rate

Creating a Quotation

POST /api/v2/quotations
Request:
{
  "fromCurrency": "COP",
  "toCurrency": "USDC",
  "amount": 100000,
  "amountIsToCurrency": false,
  "cashInMethod": "PSE",
  "cashOutMethod": "POLYGON"
}
Response:
{
  "id": "quot-9f8e7d6c-5b4a-3c2d-1e0f",
  "fromCurrency": "COP",
  "toCurrency": "USDC",
  "fromAmount": 100000,
  "toAmount": 23.81,
  "rate": 4200.50,
  "spotPrice": 4180.25,
  "expiresAt": 1704657630000,
  "cashInMethod": "PSE",
  "cashOutMethod": "POLYGON"
}
const getQuote = async (fromAmount, fromCurrency = 'COP', toCurrency = 'USDC') => {
  const response = await fetch('https://teste-94u93qnn.uc.gateway.dev/api/v2/quotations', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      fromCurrency,
      toCurrency,
      amount: fromAmount,
      amountIsToCurrency: false,
      cashInMethod: 'PSE',
      cashOutMethod: 'POLYGON'
    })
  });
  
  const quote = await response.json();
  console.log(`Rate: ${quote.rate}, You receive: ${quote.toAmount} ${toCurrency}`);
  return quote;
};

Quote Parameters

Amount Direction

The amountIsToCurrency flag determines which amount is fixed:
User specifies how much to send
{
  "fromCurrency": "COP",
  "toCurrency": "USDC",
  "amount": 100000,
  "amountIsToCurrency": false
}
Result: “Send 100,000 COP, receive ~23.81 USDC”Use when: User wants to spend exact amount of fiat

Payment Methods

Specify both cash-in and cash-out methods: Cash-In Methods (source):
  • PSE - Colombian bank payment
  • SPEI - Mexican bank transfer
  • TRANSFIYA - Colombian mobile wallet
  • ACH - US ACH transfer
  • WIRE - Wire transfer
  • POLYGON, SOLANA, etc. - Crypto networks
  • PRE_FUND - Pre-funded fiat
  • PRE_FUND_POLYGON, etc. - Pre-funded crypto
Cash-Out Methods (destination):
  • Same as cash-in, except no PRE_FUND options

Exchange Rates

Rate Components

{
  "rate": 4200.50,
  "spotPrice": 4180.25
}
spotPrice: Market rate from liquidity providers
rate: Final rate including KillB’s fees and margin
Calculation:
toAmount = fromAmount / rate
Spread = rate - spotPrice
Fee % = (spread / spotPrice) * 100

Rate Factors

Exchange rates are influenced by:
  1. Market Rate - Current market price
  2. Payment Method - Different methods have different costs
  3. Volume - Larger transactions may get better rates
  4. Network - Blockchain network affects fees
  5. Customer Tier - Your customer’s negotiated pricing
Pre-funded accounts typically receive better rates due to reduced operational costs.

Quote Expiration

Quotations expire after 30 seconds to protect against market volatility.

Handling Expiration

async function createRampWithRetry(quoteId, userId, accountId) {
  try {
    const ramp = await createRamp(quoteId, userId, accountId);
    return ramp;
  } catch (error) {
    if (error.message.includes('expired')) {
      // Get new quotation
      const newQuote = await getQuotation(/* params */);
      return await createRamp(newQuote.id, userId, accountId);
    }
    throw error;
  }
}

Countdown Timer

Show users remaining time:
function QuoteTimer({ expiresAt, onExpire }) {
  const [timeLeft, setTimeLeft] = useState(30);
  
  useEffect(() => {
    const interval = setInterval(() => {
      const remaining = Math.max(0, Math.floor((expiresAt - Date.now()) / 1000));
      setTimeLeft(remaining);
      
      if (remaining === 0) {
        onExpire();
      }
    }, 1000);
    
    return () => clearInterval(interval);
  }, [expiresAt]);
  
  return <div>Quote expires in: {timeLeft}s</div>;
}

Simulation Mode

Test quotes without creating ramps:
POST /api/v2/quotations/simulation
Same parameters as regular quotation, but:
  • No quotation ID returned
  • Rate is indicative only
  • Cannot be used to create ramp
  • No expiration
Use for:
  • Showing estimated rates
  • Calculator functionality
  • Market rate display
  • User education
// Get simulated quote for display
const simulatedQuote = await fetch('/api/v2/quotations/simulation', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    fromCurrency: 'COP',
    toCurrency: 'USDC',
    amount: userAmount,
    amountIsToCurrency: false,
    cashInMethod: 'PSE',
    cashOutMethod: 'POLYGON'
  })
}).then(r => r.json());

// Show rate to user
console.log(`Estimated rate: ${simulatedQuote.rate}`);
console.log(`You would receive: ${simulatedQuote.toAmount} USDC`);

// When user confirms, get real quotation
const realQuote = await getQuotation(/* same params */);

Quote Updates

Quotations cannot be updated. If you need a different amount or rate, create a new quotation.
// Don't do this - quotations can't be updated
// await updateQuotation(quoteId, newAmount); ❌

// Do this - create new quotation
const newQuote = await getQuotation(newAmount); // ✅

Getting Quote By ID

Retrieve a quotation after creation:
GET /api/v2/quotations/{quotationId}
Use Cases:
  • Verify quote details before ramp
  • Check if quotation is still valid
  • Audit/logging purposes

Rate Display Best Practices

Display:
- Source amount: "100,000 COP"
- Destination amount: "23.81 USDC"  
- Exchange rate: "1 USDC = 4,200.50 COP"
- Fee information: "Includes 0.5% fee"
"This rate expires in 28 seconds"

- Show visual countdown
- Warn at 10 seconds remaining
- Auto-refresh on expiration
// Auto-refresh quotes periodically
setInterval(async () => {
  const newQuote = await getQuotation(amount);
  updateDisplay(newQuote);
}, 5000); // Every 5 seconds
Show:
- "Rate: 1 USDC = 4,200.50 COP"
- "Market rate: 4,180.25 COP"
- "Spread: 0.48%"
- "Last updated: 2 seconds ago"

Error Handling

Common quotation errors:
ErrorCauseSolution
PAIR_NOT_SUPPORTEDCurrency pair unavailableCheck supported pairs
AMOUNT_TOO_SMALLBelow minimumIncrease amount
AMOUNT_TOO_LARGEExceeds user limitReduce amount or upgrade KYC
METHOD_NOT_AVAILABLEPayment method unavailableChoose different method
INSUFFICIENT_LIQUIDITYNot enough liquidityTry smaller amount or different method

Rate Comparison

Compare rates across networks:
const compareRates = async (amount) => {
  const networks = ['POLYGON', 'SOLANA', 'TRON', 'ERC20'];
  const quotes = await Promise.all(
    networks.map(network => 
      getQuotation(amount, 'COP', 'USDC', 'PSE', network)
    )
  );
  
  // Find best rate
  const best = quotes.reduce((prev, curr) => 
    curr.toAmount > prev.toAmount ? curr : prev
  );
  
  console.log(`Best rate: ${best.rate} on ${best.cashOutMethod}`);
  return best;
};

Next Steps

Create Quotations

API reference for quotations

Build Ramps

Learn how to use quotations in ramps

Pricing Guide

Best practices for displaying rates

Supported Pairs

View all available currency pairs