This guide walks institutional takers (asset managers, corporate treasuries, payment firms) through the complete trade flow: submit an order, receive competing quotes, select the best price, and execute settlement.
| SDK | REST API | SwapWidget | |
|---|---|---|---|
| Setup time | ~1 day | ~2 days | ~1 hour |
| Languages | TypeScript, Python | Any (HTTP) | React only |
| Customization | Full | Full | Theme only |
| Complexity | Low | Medium | None |
| Best for | Standard integration | Custom workflows | Quick PoC / embed |
End-to-end latency
~50 seconds
<100ms
RFQ Submit
2-5s
Auction Window
~15s
Accept + Escrow
~30s
DvP Settlement
<5s
Confirmation
Integration Checklist
Going to production? The 6 steps below assume sandbox mode. Before flipping to mainnet, read the Common Pitfalls section at the bottom - three integration mistakes account for ~80% of first-week production incidents.
Before integrating, ensure:
- Compliance attestation completed (KYC for individuals, KYB for entities)
- API key generated from the TetraFi dashboard
- Wallet funded with stablecoins on a supported chain
- Environment configured for sandbox testing
1npm install @tetrafi/sdk23# .env.local4TETRAFI_API_KEY=sk_test_...5TETRAFI_BASE_URL=https://sandbox.tetrafi.io/v16TETRAFI_ATTESTATION=... # Your compliance attestation hashThe TetraFi attestation hash (X-TetraFi-Attestation) proves your identity has been verified. Include it in all requests to access the full order book and avoid compliance-related rejections.
Broadcast your trade request to competing solvers:
1import { TetraFi } from "@tetrafi/sdk";23const tetrafi = new TetraFi({4 apiKey: process.env.TETRAFI_API_KEY!,5 environment: "sandbox",6});78const rfq = await tetrafi.rfq.create({9 pair: "USDC/USDT",10 side: "buy",11 amount: "1000000.00", // 1M USDC12 corridor: "ethereum-optimism",13 maxSlippage: 0.001, // 0.1% max slippage14});1516console.log(`RFQ created: {rfq.id}`);17console.log(`Status: {rfq.status}`); // "quoting"18console.log(`Auction ends: {rfq.expiresAt}`);Solvers compete to offer you the best price. You can poll for quotes or subscribe via WebSocket:
1// Option 1: Poll for quotes2const quotes = await tetrafi.rfq.getQuotes(rfq.id);3console.log(`Received {quotes.length} quotes:`);45quotes.forEach((q) => {6 console.log(` {q.solverId}: {q.price} ({q.confidence * 100}% confidence)`);7});89// Option 2: Real-time via WebSocket10tetrafi.events.on("quote.received", (event) => {11 console.log(`New quote: {event.quote.price} from {event.quote.solverId}`);12 console.log(` TTL: {event.quote.ttl}s | Confidence: {event.quote.confidence * 100}%`);13});The auction window is typically 2-5 seconds. You can accept a quote as soon as it arrives or wait for all quotes before choosing. Waiting the full window usually yields better pricing.
Accept the winning quote to trigger escrow creation:
1// Automatic best-price selection2const settlement = await tetrafi.rfq.acceptBest(rfq.id);3console.log("Settlement initiated:", settlement.id);45// OR manual selection for custom logic6const sorted = quotes.sort((a, b) => parseFloat(b.price) - parseFloat(a.price));7const settlement = await tetrafi.quotes.accept(sorted[0].id);8console.log("Accepted quote:", sorted[0].id, "at price:", sorted[0].price);Track the settlement through to DvP completion:
1// Subscribe to settlement events2tetrafi.events.on("settlement.pending", (event) => {3 console.log("Escrow locked:", event.settlement.escrowTxHash);4 console.log("Settlement in progress...");5});67tetrafi.events.on("settlement.complete", (event) => {8 const { settlement } = event;9 console.log("Settlement complete!");10 console.log(" Origin TX:", settlement.originTxHash);11 console.log(" Destination TX:", settlement.destinationTxHash);12});1314tetrafi.events.on("settlement.failed", (event) => {15 console.error("Settlement failed:", event.settlement.error);16 console.log("Refund TX:", event.settlement.refundTxHash);17});1819// OR poll status20const status = await tetrafi.settlements.get(settlement.id);21// status.status: "pending" | "escrow_locked" | "filling" | "complete" | "failed"Verify DvP completion and retrieve the full audit trail:
1// Fetch WORM audit trail2const audit = await tetrafi.audit.getTrail(settlement.id);3console.log("Audit entries:", audit.length);45for (const entry of audit) {6 console.log(`[{entry.type}] {entry.timestamp}: {entry.hash}`);7}89// Settlement receipt for accounting10const receipt = {11 settlementId: settlement.id,12 pair: rfq.pair,13 side: rfq.side,14 amount: rfq.amount,15 executedPrice: accepted.price,16 originTx: settlement.originTxHash,17 destTx: settlement.destinationTxHash,18 settledAt: new Date().toISOString(),19};2021await recordToAccountingSystem(receipt);The WORM audit trail provides a complete, tamper-proof record of the trade for regulatory reporting. Each entry includes a cryptographic hash linking it to the previous entry, forming an unbreakable chain of evidence.
A few things that trip up new takers most often:
Missing attestation header. The X-TetraFi-Attestation header is required on every authenticated request. Forgetting it returns 403 attestation_required and is the single most common 4xx response on first integration.
Polling too aggressively. The auction window is 2-5 seconds. Polling GET /v1/rfq/{id}/quotes more than once per second wastes rate-limit budget and never returns more data. Subscribe to the quote.received WebSocket event instead - you receive each quote as it arrives, with zero polling overhead.
Not handling settlement.failed. Atomic DvP means a failed settlement rolls back both legs and emits a settlement.failed event with a refundTxHash. Your code must subscribe to this event (or check status === "failed") and surface the refund TX to your accounting system - silently retrying the RFQ would create a phantom unsettled trade in your books.
You've completed the end-to-end taker flow. Continue building with:
- SDK Reference - full TypeScript and Python type signatures, every method documented, error handling patterns.
- Webhooks & Events - subscribe to real-time
quote.received,settlement.complete, andsettlement.failedevents instead of polling. - API Reference - interactive OpenAPI explorer for every endpoint, with try-it-now request playground.
- Architecture Overview - understand how RFQ, escrow, compliance, and DvP settlement fit together under the hood.
Ready for production? Move from sandbox to mainnet by swapping the base URL (https://api.tetrafi.io/v1) and using your live API key. The same code works against both environments - no integration changes required.