Skip to main content

Overview

The depo.to API provides simple REST endpoints to generate and manage deposit addresses across 5 blockchains (Ethereum, Arbitrum, Optimism, Polygon, Solana). Accept USDC from any supported chain and have it automatically bridge to Base network via integrated bridge providers.
Get your API key: Visit depo.to/dashboard to create an account and generate your API key

Base URL

https://api.depo.to

Authentication

All API requests require an API key in the x-api-key header:
x-api-key: your_api_key_here
Store your API key securely. Never expose it in client-side code or commit it to version control.

API Endpoints

Quick Start

Here’s a complete example to create an address group and retrieve deposit addresses:
# 1. Create address group
curl -X POST https://api.depo.to/wallet/create \
  -H "Content-Type: application/json" \
  -H "x-api-key: your_api_key_here" \
  -d '{
    "targetChain": "base",
    "targetAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "targetAsset": "USDC"
  }'

# Response includes depositAddresses array with 5 addresses

# 2. Get existing address groups
curl https://api.depo.to/wallet/addresses \
  -H "x-api-key: your_api_key_here"

How It Works

1

Create Address Group

Call /wallet/create with targetChain: "base", the destination wallet address, and targetAsset: "USDC"
2

Receive Deposit Addresses

Get deposit addresses for all supported source chains
3

User Sends USDC

Your user sends USDC to any of the generated addresses from their preferred chain
4

Automatic Bridging

depo.to automatically detects deposits (checks every 5 minutes) and bridges to Base via the integrated bridge providers
5

USDC Arrives on Base

USDC arrives at the destination address in 1-15 minutes (minus bridge, gas, & swap fees)

Rate Limits

API requests are rate-limited based on your plan. See Pricing for more details. Rate limit headers are included in responses:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1643723400
Retry-After: 30

Error Handling

All errors follow a consistent format:
{
  "error": "Error message",
  "details": "Additional information"
}

HTTP Status Codes

CodeDescription
200Success
400Bad Request - Invalid parameters
401Unauthorized - Invalid API key
404Not Found - Resource doesn’t exist
429Too Many Requests - Rate limit exceeded
500Internal Server Error

Example Error Handling

try {
  const response = await fetch('https://api.depo.to/wallet/create', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': process.env.DEPOTO_API_KEY
    },
    body: JSON.stringify(params)
  });
  
  if (!response.ok) {
    const error = await response.json();
    
    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After');
      throw new Error(`Rate limit exceeded. Retry after ${retryAfter}s`);
    }
    
    throw new Error(error.error || 'API request failed');
  }
  
  return await response.json();
  
} catch (error) {
  console.error('depo.to API error:', error);
  throw error;
}

Best Practices

  • Store API keys in environment variables
  • Never commit keys to version control
  • Use different keys for development and production
  • Rotate keys regularly
Deposit addresses don’t change - cache them to reduce API calls:
const addressCache = new Map();

async function getAddresses(targetAddress) {
  if (addressCache.has(targetAddress)) {
    return addressCache.get(targetAddress);
  }
  
  const response = await fetch(
    `https://api.depo.to/wallet/addresses?targetAddress=${targetAddress}`,
    { headers: { 'x-api-key': API_KEY } }
  );
  const data = await response.json();
  addressCache.set(targetAddress, data.addressGroups[0].depositAddresses);
  return data.addressGroups[0].depositAddresses;
}
Handle transient errors with exponential backoff:
async function retryRequest(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error.status !== 429 && error.status !== 500) {
        throw error; // Don't retry client errors
      }
      if (i === maxRetries - 1) throw error;
      
      const delay = Math.pow(2, i) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}
Poll the /wallet/addresses endpoint to track deposits:
async function waitForDeposit(targetAddress, timeout = 300000) {
  const startTime = Date.now();
  
  while (Date.now() - startTime < timeout) {
    const response = await fetch(
      `https://api.depo.to/wallet/addresses?targetAddress=${targetAddress}`,
      { headers: { 'x-api-key': API_KEY } }
    );
    const data = await response.json();
    
    // Check if any deposits have been detected
    // Note: Backend currently doesn't expose transaction status
    // but monitors deposits every 5 minutes automatically
    
    if (data.success && data.count > 0) {
      return data.addressGroups;
    }
    
    await new Promise(resolve => setTimeout(resolve, 60000)); // Poll every 60s
  }
  
  throw new Error('Timeout waiting for deposit');
}

Next Steps