Skip to main content

Get started in three steps

Integrate our API into your application with this quick guide.

Step 1: Get Your First Quote

Start by requesting a swap quote to see available routes and prices.
curl --location 'https://api.dkit.xyz/v1/quote' \
--header 'Content-Type: application/json' \
--header 'api-key: 86c3fc76-25c8-455c-8d6d-0ecea88d0f6e' \
--data '{
    "sellAsset": "ZEC.ZEC",
    "sellAmount": "2",
    "buyAsset": "ETH.ETH",
    "slippage": 1,
    "affiliate": "eld",
    "affiliateFee": 88,
    "includeTx": true,
    "providers": [
        "MAYACHAIN"
    ],
    "sourceAddress": "t1Tmw3syVocrsRUDuCq7jteVjMSNfwpgz88",
    "destinationAddress": "0x817bFA97Cc8E5Bfa499D401f43E3087B07AE96f9"
}'

Step 2: Execute the Swap

Use the transaction details from the quote to execute the swap on-chain.
For native cross-chain swaps (e.g., BTC to ETH via THORChain):
const route = quote.routes[0]; // Select best route

// Send native transaction to the inbound address with memo
const tx = {
  to: route.inboundAddress,
  value: sellAmount,
  memo: route.memo // Required for THORChain/Maya
};

// Execute with your wallet
const txHash = await wallet.sendTransaction(tx);

Step 3: Track the Swap

Monitor your swap progress in real-time.
const trackSwap = async (txHash, chainId, quoteId, routeIndex) => {
  const response = await fetch('https://api.dkit.xyz/v1/track', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': '86c3fc76-25c8-455c-8d6d-0ecea88d0f6e'
    },
    body: JSON.stringify({
      hash: txHash,
      chainId: chainId,
      quoteId: quoteId,
      routeIndex: routeIndex
    })
  });
  
  const tracking = await response.json();
  
  if (tracking.success) {
    console.log(`Status: ${tracking.data.trackingStatus}`);
    
    // Check if complete
    if (tracking.data.trackingStatus === 'completed') {
      console.log(`Output tx: ${tracking.data.trackMeta.outputTxHash}`);
    }
  }
  
  return tracking;
};

// Poll for updates
const pollStatus = async (params) => {
  let status = 'not_started';
  
  while (status !== 'completed' && status !== 'refunded') {
    const result = await trackSwap(params);
    
    if (result.success) {
      status = result.data.trackingStatus;
      console.log(`Current status: ${status}`);
    }
    
    await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
  }
};

Complete Example

Here’s a complete example that ties everything together:
async function performSwap() {
  try {
    // 1. Get quote
    const quote = await fetch('https://api.dkit.xyz/v1/quote', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        sellAsset: 'ETH.ETH',
        buyAsset: 'BTC.BTC',
        sellAmount: '1.0',
        sourceAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8',
        destinationAddress: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
        slippage: 3
      })
    }).then(r => r.json());
    
    console.log(`Got ${quote.routes.length} routes`);
    
    // 2. Select best route
    const route = quote.routes[0];
    console.log(`Best route: ${route.providers.join(' → ')}`);
    console.log(`Expected output: ${route.expectedBuyAmount} sats`);
    
    // 3. Execute swap (implementation depends on your wallet)
    const txHash = await executeSwap(route);
    console.log(`Transaction sent: ${txHash}`);
    
    // 4. Track the swap
    let tracking;
    do {
      tracking = await fetch('https://api.dkit.xyz/v1/track', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          hash: txHash,
          chainId: '1', // Ethereum mainnet
          quoteId: quote.quoteId,
          routeIndex: 0
        })
      }).then(r => r.json());
      
      if (tracking.success) {
        console.log(`Status: ${tracking.data.trackingStatus}`);
        
        if (tracking.data.isStreaming) {
          const progress = tracking.data.streamingProgress;
          console.log(`Streaming: ${progress.percentage}% complete`);
        }
      }
      
      await new Promise(r => setTimeout(r, 5000)); // Wait 5 seconds
      
    } while (
      tracking.success && 
      !['completed', 'refunded'].includes(tracking.data.trackingStatus)
    );
    
    if (tracking.data.trackingStatus === 'completed') {
      console.log('Swap completed successfully!');
      console.log(`Output tx: ${tracking.data.trackMeta.outputTxHash}`);
    }
    
  } catch (error) {
    console.error('Swap failed:', error);
  }
}

Next Steps

API Reference

Explore all available endpoints and parameters

Quote Endpoint

Deep dive into quote requests and responses

Error Handling

Learn how to handle errors gracefully

Getting Quotes Guide

Advanced strategies for optimizing quotes

Common Integration Patterns

// MetaMask example
const executeEVMSwap = async (route) => {
  const accounts = await ethereum.request({ 
    method: 'eth_requestAccounts' 
  });
  
  const tx = {
    from: accounts[0],
    to: route.targetAddress || route.inboundAddress,
    value: route.tx?.value || '0x0',
    data: route.tx?.data || route.memo || '0x'
  };
  
  return await ethereum.request({
    method: 'eth_sendTransaction',
    params: [tx]
  });
};
const swapWithRetry = async (params, maxRetries = 3) => {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const quote = await getQuote(params);
      
      if (quote.routes.length > 0) {
        return await executeSwap(quote.routes[0]);
      }
      
      // Check provider errors
      if (quote.providerErrors) {
        const retriable = quote.providerErrors.some(e => 
          e.errorCode === 'RATE_LIMITED' || 
          e.errorCode === 'PROVIDER_UNAVAILABLE'
        );
        
        if (!retriable) throw new Error('No routes available');
      }
      
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
    }
  }
};
// Convert human-readable amounts to base units
const toBaseUnits = (amount, decimals) => {
  const factor = BigInt(10 ** decimals);
  const [whole, fraction = ''] = amount.split('.');
  const fractionPadded = fraction.padEnd(decimals, '0').slice(0, decimals);
  return (BigInt(whole) * factor + BigInt(fractionPadded)).toString();
};

// Convert base units to human-readable
const fromBaseUnits = (amount, decimals) => {
  const value = BigInt(amount);
  const factor = BigInt(10 ** decimals);
  const whole = value / factor;
  const remainder = value % factor;
  
  if (remainder === 0n) return whole.toString();
  
  const fraction = remainder.toString().padStart(decimals, '0');
  return `${whole}.${fraction.replace(/0+$/, '')}`;
};