Skip to main content
Use the Daimo API directly to build a custom deposit experience. This works with any language or framework, no React required.

Overview

The deposit flow has four steps:
  1. Create a session: server-side, with your API key
  2. Choose a payment method: client-side, with the client secret
  3. Wait for deposit: show the deposit address, poll for status
  4. Handle completion: process the result

Step 1: Create a session

Create a session on your server. Never expose your API key to the client.
curl -X POST https://api.daimo.com/v1/sessions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "destination": {
      "type": "evm",
      "address": "0xYourAddress",
      "chainId": 8453,
      "tokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "amountUnits": "10.00"
    },
    "display": {
      "title": "Deposit to Acme",
      "verb": "Deposit"
    }
  }'
Pass session.clientSecret and session.sessionId to your client.

Step 2: Choose a payment method

On the client, call the payment methods endpoint. This transitions the session from requires_payment_method to waiting_payment. EVM deposit (any EVM chain):
curl -X POST https://api.daimo.com/v1/sessions/{sessionId}/paymentMethods \
  -H "Content-Type: application/json" \
  -d '{
    "clientSecret": "SESSION_CLIENT_SECRET",
    "paymentMethod": { "type": "evm" }
  }'
The response includes a receiverAddress in result.session.paymentMethod. Display this EVM address to the user - they send tokens to it from any supported chain.
{
  "session": {
    "status": "waiting_payment",
    "paymentMethod": {
      "type": "evm",
      "receiverAddress": "0x1a2B3c4D5e6F...",
      "createdAt": 1700000000
    }
  }
}
Tron USDT deposit:
curl -X POST https://api.daimo.com/v1/sessions/{sessionId}/paymentMethods \
  -H "Content-Type: application/json" \
  -d '{
    "clientSecret": "SESSION_CLIENT_SECRET",
    "paymentMethod": { "type": "tron", "amountUsd": 10.0 }
  }'
The response includes a tron.receiverAddress in result.session.paymentMethod, a temporary Tron address. Display it to the user so they can send USDT to it.
{
  "session": {
    "status": "waiting_payment",
    "paymentMethod": {
      "type": "tron",
      "receiverAddress": "TXyz1234...",
      "createdAt": 1700000000
    }
  }
}
Solana deposit:
curl -X POST https://api.daimo.com/v1/sessions/{sessionId}/paymentMethods \
  -H "Content-Type: application/json" \
  -d '{
    "clientSecret": "SESSION_CLIENT_SECRET",
    "paymentMethod": {
      "type": "solana",
      "walletAddress": "So1ana...",
      "inputTokenMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "amountUsd": 10.0
    }
  }'
The response includes solana.serializedTx, a hex-encoded serialized Solana transaction for the user’s wallet to sign and submit. This preserves a one-click wallet experience on Solana: swap and burn actions are bundled into one signed transaction. Unlike EVM and Tron, there is no receiverAddress for type: "solana".
{
  "session": {
    "status": "waiting_payment",
    "paymentMethod": {
      "type": "solana",
      "createdAt": 1700000000
    }
  },
  "solana": {
    "serializedTx": "0xabc123..."
  }
}

Step 3: Wait for session completion

Poll for status updates to the session after the user has paid.
curl -X PUT https://api.daimo.com/v1/sessions/{sessionId}/check \
  -H "Content-Type: application/json" \
  -d '{ "clientSecret": "SESSION_CLIENT_SECRET" }'
If you know the user’s transaction hash, pass it as txHash to speed up detection.

Step 4: Handle completion

Check for terminal statuses:
  • succeeded - funds delivered
  • bounced - delivery failed (e.g. contract call reverted). Funds returned to refund address.
  • expired - session timed out
In the succeeded and bounced case, destination.delivery.txHash refers to the settlement transaction.