Skip to content

Quote

The first step in every sweep is requesting a quote. The quote locks in:

  • The fee breakdown (protocol fee + builder fee)
  • The unsigned SweepOrder the user will sign
  • The expiry time

Request

POST https://api.sweepster.xyz/quote
Content-Type: application/json

Body

typescript
interface QuoteRequestWire {
  owner: string;            // "0x..." — user's wallet address (40-hex 0x address)
  tokenIn: string;          // "0x..." — source token contract address
  amountIn: string;         // decimal string, e.g. "1000000" (1 USDC)
  tokenOut: string;         // "0x..." — destination token contract address
  destination: string;      // "0x..." — recipient address on destination chain
  destChainId: number;      // destination chain ID (e.g. 42161 for Arbitrum)
  tier: "tier1" | "tier2" | "tier3";   // token risk tier
  route: string;            // hint, e.g. "base->arbitrum" or "base->base"
  subscriptionActive: boolean;
  userId: string;           // unique user identifier for fee policy
  apiKey?: string;          // optional — your builder API key for attribution
}

Example

typescript
const quoteBody = {
  owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
  tokenIn: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",  // USDC on Base
  amountIn: "1000000",      // 1 USDC (6 decimals)
  tokenOut: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",  // USDC on Arbitrum
  destination: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
  destChainId: 42161,
  tier: "tier1",
  route: "base->arbitrum",
  subscriptionActive: false,
  userId: "user_abc",
  apiKey: "sk_live_...",
};

const res = await fetch("https://api.sweepster.xyz/quote", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(quoteBody),
});

Response

typescript
interface QuoteResponseWire {
  quote: {
    id: string;             // quote / intent ID (UUID)
    crossChain: boolean;    // true if destChainId != source chain
    expiresAtMs: number;    // UNIX ms — quote expires at this time
    total: string;          // total fee as decimal string (protocolFee + builderFee)
    builderId?: string;     // builder ID if attributed
  };
  order: SweepOrderWire;    // the unsigned order to sign
}

The order returned is the SweepOrderWire with all uint256 fields serialized as decimal strings:

typescript
interface SweepOrderWire {
  owner: string;            // "0x..."
  tokenIn: string;          // "0x..."
  amountIn: string;         // decimal string
  feeAmount: string;        // decimal string — protocol fee
  builder: string;          // "0x..." — builder address (zero address if unattributed)
  builderFee: string;       // decimal string — builder's cut
  tokenOut: string;         // "0x..."
  minAmountOut: string;     // decimal string (0 for cross-chain)
  destination: string;      // "0x..."
  swapTarget: string;       // "0x..." — DEX router / bridge address
  swapCalldata: string;     // "0x..." — encoded swap/bridge call
  deadline: string;         // decimal string — UNIX seconds
  nonce: string;            // decimal string
  destChainId: string;      // decimal string
}

Error responses

StatusMeaning
422Invalid input (field validation failed) or token declined by risk engine
429Rate limit exceeded (100 req/min per IP by default)
json
HTTP 422
{ "error": "token declined: insufficient liquidity" }

Quote expiry

Quotes expire at expiresAtMs. A user must sign and submit before expiry. The orchestrator rejects submissions for expired quotes.

Next step

Sign the order →

Non-custodial · Atomic · Audit + bug bounty planned before mainnet value.