5 minute guide
Build your first compliant DeFi transaction in under 5 minutes.
ILAL's ComplianceHook rejects every on-chain transaction from a wallet without an active compliance session. The API will build and return a valid unsigned TX — but when you broadcast it, the chain will revert. Step 2 activates your session. Do it before calling any DeFi endpoint.
Register at ilal.tech/login, then go to the API Keys dashboard and click Create API Key.
ilal_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxOne call. Handles registration + session activation in a single request. No ZK proof required on testnet. The relayer pays gas.
curl -X POST https://ilal-mvp-production.up.railway.app/api/v1/testnet/activate \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"walletAddress": "YOUR_WALLET_ADDRESS"}'{
"success": true,
"walletAddress": "0x...",
"txHash": "0x...",
"expiresAt": "2026-04-05T14:00:00.000Z",
"note": "Testnet only — ZK proof bypassed."
}durationHours to extend up to 720h.POST /testnet/activate-batch with {"wallets": ["0x...", "0x..."]} for up to 20 wallets at once.Verify your session is active:
curl https://ilal-mvp-production.up.railway.app/api/v1/session/YOUR_WALLET_ADDRESS \
-H "X-API-Key: YOUR_API_KEY"
# → { "isActive": true, "remainingSeconds": 86342 }POST /onboarding/registerGET /onboarding/attestation/:addressPOST /verifyCall POST /defi/swap. Returns unsigned calldata plus a live preflight that simulates the TX on-chain before returning.
curl -X POST https://ilal-mvp-production.up.railway.app/api/v1/defi/swap \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tokenIn": "0x4200000000000000000000000000000000000006",
"tokenOut": "0xa486Fb51ED09B970A23F7Fe910bc90089f78424D",
"amount": "1000000000000000",
"userAddress": "YOUR_WALLET_ADDRESS"
}'{
"success": true,
"transaction": { "to": "0x...", "data": "0x...", "value": "0x0", "chainId": 84532, "gas": "0x1E8480" },
"preflight": {
"sessionActive": true,
"canBroadcastSafely": true,
"simulation": { "success": true }
}
}canBroadcastSafely is false — do not broadcast. Check preflight.simulation.revertReason for the exact cause. Most common: session expired → re-run Step 2.Take result.transaction and send it with your own signer.
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { baseSepolia } from 'viem/chains';
const account = privateKeyToAccount(YOUR_PRIVATE_KEY);
const wallet = createWalletClient({ account, chain: baseSepolia, transport: http() });
// Step 2: activate (if not already done)
await fetch('https://ilal-mvp-production.up.railway.app/api/v1/testnet/activate', {
method: 'POST',
headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ walletAddress: account.address }),
});
// Step 3: build
const res = await fetch('https://ilal-mvp-production.up.railway.app/api/v1/defi/swap', {
method: 'POST',
headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({
tokenIn: '0x4200000000000000000000000000000000000006',
tokenOut: '0xa486Fb51ED09B970A23F7Fe910bc90089f78424D',
amount: '1000000000000000',
userAddress: account.address,
}),
});
const { transaction, preflight } = await res.json();
// Guard: never broadcast if simulation failed
if (!preflight.canBroadcastSafely) {
throw new Error(`Cannot broadcast: ${preflight.simulation?.revertReason}`);
}
// Step 4: send
const hash = await wallet.sendTransaction({
to: transaction.to,
data: transaction.data,
value: BigInt(transaction.value),
});
console.log('Confirmed:', hash);If something isn't working, run through this in order:
GET /health200 — API reachableWrong URL or network issueGET /usage/stats (X-API-Key)200 — key worksCheck error.code: API_KEY_FORMAT_INVALID / API_KEY_HASH_MISMATCHPOST /testnet/activatetxHash — session active500 → check VERIFIER_PRIVATE_KEY on server sideGET /session/:addressisActive: trueSession not yet on-chain — wait 1 block and retryGET /preflight/:addresscanSwap: trueCheck readiness.issues[] for missing allowances or balancePOST /defi/swapcanBroadcastSafely: trueCheck simulation.revertReason — session / allowance / pool depthSign + BroadcastOn-chain confirmedcanBroadcastSafely was false — never broadcast if false