Integrate Payments

Add deposit tracking and payment configuration to your application.

12 minAdvanced

Prerequisites

  • A DUAL organization with billing enabled
  • Familiarity with crypto tokens (ERC-20)

What You'll Build

DUAL supports on-chain payments for tokenized assets. In this tutorial you'll configure the payment system, track deposits, and query balance and transaction history for your organization.

Step 1 — Check Payment Config

First, retrieve your organization's payment configuration to see supported tokens and deposit addresses:

bash
curl https://gateway-48587430648.europe-west6.run.app/payments/config \
  -H "Authorization: Bearer $DUAL_TOKEN"

The response includes:

FieldDescription
multi_token_deposit_addressThe address where users send tokens
vee_addressVEE token contract address
supported_tokensArray of accepted ERC-20 tokens

Step 2 — Monitor Deposits

Once a user sends tokens to the deposit address, DUAL detects them automatically. List deposits with optional filters:

bash
# List all deposits
curl https://gateway-48587430648.europe-west6.run.app/payments/deposits \
  -H "Authorization: Bearer $DUAL_TOKEN"

# Filter by transaction hash
curl "https://gateway-48587430648.europe-west6.run.app/payments/deposits?tx_hash=0xabc..." \
  -H "Authorization: Bearer $DUAL_TOKEN"

# Filter by token
curl "https://gateway-48587430648.europe-west6.run.app/payments/deposits?token=VEE" \
  -H "Authorization: Bearer $DUAL_TOKEN"

Step 3 — Check Organization Balance

Track your organization's running balance and credit history:

bash
# Current balance
curl https://gateway-48587430648.europe-west6.run.app/organizations/{orgId}/balance \
  -H "Authorization: Bearer $DUAL_TOKEN"

# Balance history (credits and debits over time)
curl https://gateway-48587430648.europe-west6.run.app/organizations/{orgId}/balance/history \
  -H "Authorization: Bearer $DUAL_TOKEN"

Step 4 — Implement in Your App

Here's a complete JavaScript example that polls for new deposits and updates a UI:

javascript
const API_BASE = 'https://gateway-48587430648.europe-west6.run.app';

async function checkDeposits(token) {
  const res = await fetch("" + API_BASE + "/payments/deposits", {
    headers: {
      'Authorization': "Bearer " + token + "",
      'Content-Type': 'application/json'
    }
  });
  const data = await res.json();
  return data.items || [];
}

async function getBalance(token, orgId) {
  const res = await fetch(
    "" + API_BASE + "/organizations/" + orgId + "/balance",
    { headers: { 'Authorization': "Bearer " + token + "" } }
  );
  return res.json();
}

// Poll every 30 seconds
setInterval(async () => {
  const deposits = await checkDeposits(AUTH_TOKEN);
  const balance = await getBalance(AUTH_TOKEN, ORG_ID);
  updateUI(deposits, balance);
}, 30000);
Production Tip: Instead of polling, combine this with webhooks to receive instant notifications when deposits are confirmed. Register a webhook for payment.deposit.confirmed events.

Summary

You've now set up the payment pipeline: configuration, deposit tracking, balance monitoring, and a client-side integration pattern. For the full payments API reference, see Payments API.