v1.6.0·EIP-712 + EIP-7702

Q402 Developer Docs

Everything you need to add gasless USDC payments to your product. One API. Any EVM chain. Zero gas for your users.

Overview

Q402 is a managed relay layer for stablecoin paymentsacross EVM chains. Your product sends USDC or USDT from a user's wallet without the user ever holding a native token — Q402's relayer submits the on-chain transaction and pays the gas.

Architectureend-to-end flow
  User wallet              Q402 API                 On-chain                 Your app
  ───────────              ────────                 ────────                 ────────

  1. Sign EIP-712  ──▶  /api/payment/intent   lock quote, planChain
                        /api/payment/activate scan TX, grant credits
  2. Get API key   ◀──  (sandbox or live)

  3. Call pay()    ──▶  /api/relay            ──▶  EIP-7702 Type-4 TX
                        verify · decrement         USDC/USDT transfer
                        credits · cap checks       user EOA ──▶ recipient
                                                                          ◀── webhook
                                                                              HMAC-signed
                                                                              relay.success

                        Dashboard ◀── delivery log · key rotation · gas tank balance

Three moving parts: an intent that locks the quote before payment, an activate step that scans the on-chain transfer and issues credits, and a relay that submits gasless payments for your users. Every relay can fire a signed webhook and is recorded for audit.

What is an API?

An API is just a URL your server calls. Like ordering food at a restaurant — you send a request ("here's a user's signed transaction"), Q402's server handles the work, and sends back a result ("done, txHash: 0xabc..."). No blockchain expertise needed on your end.

Protocol
EIP-712 + EIP-7702
Settlement token
USDC · USDT
Gas source
Your gas pool

How It Works

Three actors. One transaction. Zero gas for your users.

A
User signs an authorization (no gas, no blockchain)
Using their wallet (e.g. MetaMask), the user signs a typed message saying "I allow transferring X USDC to address Y". This is purely a cryptographic signature — no transaction is sent, no gas is needed.
B
Your server calls POST /api/relay
You pass the user's signature to Q402's API. That's it — one HTTP call. Q402 verifies the signature, constructs the on-chain transaction, and submits it.
C
Gas is deducted from your gas pool, USDC lands in recipient wallet
Q402 uses your pre-funded gas pool to pay the network fee. The USDC moves on-chain, verifiable on BscScan / Snowtrace / Etherscan. User sees zero gas cost.
// Full flow
User wallet → signs EIP-712 → your frontend
Your backend → POST /api/relay → Q402 API
Q402 → uses gas pool → on-chain TX
Chain → confirms TX → recipient gets USDC

Quick Start

Get your first gasless transaction running in under 5 minutes.

1 · Load the SDK

html
<script src="https://q402.quackai.ai/q402-sdk.js"></script>

2 · One-line gasless payment (client-side)

javascript
// Initialize once with your API key + chain
const q402 = new Q402Client({
  apiKey: "q402_live_YOUR_KEY",
  chain:  "bnb",   // "bnb" | "avax" | "eth" | "xlayer" | "stable" | "mantle" | "injective"
});
// Note: when chain is "injective", only token: "USDT" is supported.
// Native USDC via Circle CCTP is announced for Q2 2026.

// Wallet popup appears — user signs, Q402 relays on-chain
// amount MUST be a human-readable decimal STRING (e.g. "50.00", "0.123456").
// Never pass a JS Number — IEEE-754 loses precision on 18-decimal tokens.
// Inputs exceeding the token's decimals or non-decimal strings throw.
const result = await q402.pay({
  to:     recipientAddress,
  amount: "50.00",
  token:  "USDC",
});
// result → { success: true, txHash: "0xabc...", tokenAmount: "50", chain: "bnb" }

3 · Injective EVM (USDT-only)

Native USDC via Circle CCTP is announced for Q2 2026; until then, Injective uses USDT as the only payment token. The SDK gates this explicitly — passing token: "USDC" with chain: "injective" throws before any signature is requested, and the relay route enforces the same allowlist server-side.

javascript
const q402 = new Q402Client({
  apiKey: "q402_live_YOUR_KEY",
  chain:  "injective",
});

const result = await q402.pay({
  to:     recipientAddress,
  amount: "50.00",
  token:  "USDT",   // required — USDC not yet supported on Injective
});

4 · That's it

typescript
// Full result shape:
// {
//   success:       true,
//   txHash:        "0xdef456...",
//   chain:         "bnb",
//   blockNumber:   "38482910",
//   tokenAmount:   "50",
//   token:         "USDC",
//   gasCostNative: 0.000021,
//   method:        "eip7702",
// }
console.log("Paid! TX:", result.txHash);
Tip
The SDK handles signing and relay in one call — no separate backend step needed. The user never touches BNB, ETH, or AVAX. Gas is deducted from your pre-funded gas pool automatically.

Claude MCP

Q402 ships as a Model Context Protocol server so Claude Desktop, Claude Code, Cline, and any other MCP-compatible AI client can quote and (optionally) settle gasless USDC and USDT payments directly from a chat. The package is @quackai/q402-mcp on npm and bitgett/q402-mcp on GitHub.

1 · Install

bash
# Claude Code CLI
claude mcp add q402 -- npx -y @quackai/q402-mcp

# Or paste this into claude_desktop_config.json:
# (macOS:   ~/Library/Application Support/Claude/claude_desktop_config.json)
# (Windows: %APPDATA%\Claude\claude_desktop_config.json)
{
  "mcpServers": {
    "q402": {
      "command": "npx",
      "args": ["-y", "@quackai/q402-mcp"]
    }
  }
}

2 · Tools exposed

ToolAuthPurpose
q402_quoteno authCompare gas cost + supported tokens across chains. Read-only.
q402_balanceapi keyVerify the configured key and report its plan tier (live vs sandbox).
q402_payapi key + signer + flagSend a gasless payment. Sandbox by default — see below.

3 · Sandbox vs live mode

By default q402_pay runs in sandbox — it returns a deterministic-looking fake transaction hash, no funds move, no gas-tank credit is consumed. To enable real on-chain transactions, all three environment variables must be set:

bash
Q402_API_KEY=q402_live_...      # live-tier key from /dashboard
Q402_PRIVATE_KEY=0xabc...       # signer for the payer EOA
Q402_ENABLE_REAL_PAYMENTS=1     # explicit opt-in

Anything missing → automatic sandbox fallback with a hint pointing at what to set. Two additional guards run regardless of mode: Q402_MAX_AMOUNT_PER_CALL (default $5) caps any single call, and Q402_ALLOWED_RECIPIENTS optionally restricts to an address allowlist.

Tip
The q402_pay tool description tells the model to ALWAYS get explicit user confirmation of recipient + amount in chat before invoking. Combined with the sandbox default + cap + allowlist, that gives four layers of safety before any wei moves.

Gas Pool

Q402 uses a gas pool model. You deposit native tokens (BNB, ETH, MNT, AVAX, INJ, OKB, or USDT0 on Stable) into a single Q402-managed Gas Tank address that is shared across all customers — your balance is tracked off-chain, per wallet, in our ledger. Every time a user transaction is relayed, the gas fee is automatically deducted from your per-wallet balance.

Deposit

Send native tokens (BNB / ETH / MNT / AVAX / INJ / OKB / USDT0 on Stable) to the Q402 Gas Tank address shown in your dashboard. Your balance is tracked per wallet address. Note: the Gas Tank is a separate cold wallet from the hot relayer — never send funds to the relayer address directly.

Auto-deduction

Each relayed transaction deducts the actual gas cost in native tokens. Balances update in real time.

Withdraw

Withdrawals are processed manually by Q402 operations. Contact business@quackai.ai to request a refund. Funds always remain yours.

Important
If your gas pool is empty, transactions will fail. Monitor the balance in your dashboard — and opt in to TX-credit email alerts (fire at 20 % / 10 % remaining) from the dashboard's Alerts panel. Top up via the dashboard or send native tokens directly to the Gas Tank address.

Authentication

All relay requests require your API key in the apiKey field of the request body. Connect your wallet to get a sandbox key (q402_test_*) immediately. Your live key (q402_live_*) is issued automatically once your on-chain payment is confirmed on /payment.

json
// POST /api/relay
{
  "apiKey": "q402_live_YOUR_API_KEY",
  "chain":  "avax",
  "token":  "USDC",
  ...
}
q402_live_*
Production key. Transactions hit mainnet. Keep this key private — it is tied to your gas tank.

API Reference

Base URL: https://q402.quackai.ai/api

POST/relay

Submit a signed EIP-712 + EIP-7702 payload. Q402 verifies the signature and relays the transaction on-chain using your gas pool.

json
// Request body
{
  "apiKey":      "q402_live_YOUR_API_KEY",
  "chain":       "avax",           // avax | bnb | eth | xlayer | stable | mantle | injective
  "token":       "USDC",           // USDC | USDT
  "from":        "0xUserWallet...",
  "to":          "0xRecipient...",
  "amount":      "50000000",       // atomic units (6 decimals = 50 USDC)
  "deadline":    1751289600,
  "witnessSig":  "0xabc123...",
  "authorization": { ... }         // EIP-7702 authorization object
}

// Response 200
// All numeric amounts are returned as decimal strings to preserve
// 18-decimal token precision (IEEE-754 doubles lose precision at that scale).
{
  "success":        true,
  "txHash":         "0xdef456...",
  "chain":          "avax",
  "blockNumber":    "54540550",
  "tokenAmount":    "50",
  "gasCostNative":  "0.000021",
  "method":         "eip7702"
}
GET/relay/info

Returns the relayer (facilitator) wallet address. Call this before constructing any TransferAuthorization — the facilitator field in the EIP-712 payload must match this value on all chains.

json
// GET /api/relay/info
{ "facilitator": "0xRelayerAddress..." }

Chain Support

Same API, same SDK — regardless of which chain. Switch with one parameter.

Chainchain paramChain IDGas tokenStatusAvg gas/tx
BNB Chain
bnb56BNBMainnet Live~$0.001
Ethereum
eth1ETHMainnet Live~$0.19
Avalanche
avax43114AVAXMainnet Live~$0.002
X Layer
xlayer196OKBMainnet Live~$0.001
Stable
stable988USDT0 ★Mainnet Live~$0.001
Mantle
mantle5000MNTMainnet Live~$0.001
Injective
injective1776INJMainnet Live~$0.10
Note
Gas costs are deducted from your gas pool— not from Q402's pocket, not from your users. Ethereum gas is significantly higher; consider funding a larger pool for ETH.
Important
★ Stable chain: USDT0 is both the gas token and the payment token on Stable (Chain ID 988). Your Gas Tank must be funded with USDT0 — not a native coin. Users also send USDT0 when making payments on this chain.

EIP-712 Signing

Q402 uses EIP-712 typed structured data signing — the same standard used by Uniswap, Compound, and major DeFi protocols. The user signs a human-readable message. No gas. No blockchain interaction.

Contract Addresses & Domain Names

typescript
// Implementation contract per chain
const CONTRACTS = {
  avax:   "0x96a8C74d95A35D0c14Ec60364c78ba6De99E9A4c", // Q402 Avalanche (chainId: 43114)
  bnb:    "0x6cF4aD62C208b6494a55a1494D497713ba013dFa", // Q402 BNB Chain (chainId: 56)
  eth:    "0x8E67a64989CFcb0C40556b13ea302709CCFD6AaD", // Q402 Ethereum  (chainId: 1)
  xlayer: "0x8D854436ab0426F5BC6Cc70865C90576AD523E73", // Q402 X Layer   (chainId: 196)
  stable: "0x2fb2B2D110b6c5664e701666B3741240242bf350", // Q402 Stable    (chainId: 988)
  mantle: "0x2fb2B2D110b6c5664e701666B3741240242bf350", // Q402 Mantle    (chainId: 5000)
  injective: "0x2fb2B2D110b6c5664e701666B3741240242bf350", // Q402 Injective (chainId: 1776)
};

// EIP-712 domain name — must match contract NAME constant exactly
const DOMAIN_NAMES = {
  avax:      "Q402 Avalanche",
  bnb:       "Q402 BNB Chain",
  eth:       "Q402 Ethereum",
  xlayer:    "Q402 X Layer",
  stable:    "Q402 Stable",
  mantle:    "Q402 Mantle",
  injective: "Q402 Injective",
};

// verifyingContract:
//   ALL chains → user's own EOA  (address(this) under EIP-7702 delegation)

Witness Type (unified across all chains)

typescript
// Every deployed Q402 impl contract uses the same EIP-712 typed struct:
const types = {
  TransferAuthorization: [
    { name: "owner",       type: "address" }, // token sender (user's EOA)
    { name: "facilitator", type: "address" }, // gas sponsor (Q402 relayer)
    { name: "token",       type: "address" }, // ERC-20 contract (USDC / USDT / USDT0)
    { name: "recipient",   type: "address" }, // payment destination
    { name: "amount",      type: "uint256" }, // atomic units
    { name: "nonce",       type: "uint256" }, // random uint256, replay protection
    { name: "deadline",    type: "uint256" }, // unix timestamp
  ],
};

// verifyingContract is ALWAYS the user's own EOA — the contract computes its
// domain separator with address(this), which equals the user EOA under EIP-7702.

Signing with ethers.js

typescript
// Fetch facilitator address first (required for all chains)
const { facilitator } = await fetch("https://q402.quackai.ai/api/relay/info").then(r => r.json());

const domain = {
  name:              DOMAIN_NAMES[chain],
  version:           "1",
  chainId:           chainId,
  verifyingContract: userAddress,  // user's own EOA — same for all chains under EIP-7702
};

const nonce = ethers.toBigInt(ethers.randomBytes(32)); // random uint256

const signature = await signer.signTypedData(domain, types, {
  owner:       userAddress,
  facilitator,
  token:       tokenAddress,
  recipient:   recipientAddress,
  amount:      ethers.parseUnits("50", decimals), // 6 decimals on most chains; 18 only for Stable chain's USDT0
  nonce,
  deadline:    BigInt(Math.floor(Date.now() / 1000) + 600),
});
Note
EIP-7702 note: All supported chains (BNB, ETH, Avalanche, X Layer, Stable, Mantle, Injective) use EIP-7702 Type 4 transactions. The relayer submits one transaction that delegates impl code to the user's EOA and executes the transfer atomically. X Layer additionally supports EIP-3009 as a fallback (pass eip3009Nonce instead of authorization).
Important
Stable chain: USDT0 here has 18 decimals (not 6). Use ethers.parseUnits(amount, 18). The gas pool must also be funded in USDT0 — there is no separate native gas coin. (Note: USDT0 on Mantle uses the same OFT address but 6 decimals, matching the other chains.)

Error Responses

Errors return a JSON body of the form { "error": string, "code"?: string }. The HTTP status conveys the failure class; error is a human-readable message and code (when present) is a stable machine-readable tag for programmatic handling.

Most failure modes today return only error (no code). The codes listed below are the stable tags currently emitted by the server.

400
(no code)
Generic validation failure — malformed JSON, missing required field, or chain-specific shape error. The error message describes the offending field.
401
(no code)
Missing or invalid API key, or API key has been rotated.
401
NONCE_EXPIRED
Auth challenge has expired or already been consumed. Fetch a fresh nonce from /api/auth/nonce.
401
SIG_MISMATCH
Auth signature does not match the expected challenge for the given address.
402
(no code)
Insufficient gas tank balance for the selected chain. Top up via dashboard.
402
NO_INTENT
Activate called without a prior /api/payment/intent — call intent first to lock the quote.
402
INTENT_MISMATCH
Activate intentId does not match the stored latest intent for this address.
402
SENDER_MISMATCH
On-chain TX sender does not match the calling wallet address.
402
CHAIN_MISMATCH
On-chain payment was found but on a different chain than the intent specified.
402
TOKEN_MISMATCH
On-chain payment used a different ERC-20 than the intent specified.
402
AMOUNT_LOW
On-chain payment amount is below the intent's expectedUSD threshold.
403
(no code)
Subscription expired. Renew on /payment to continue.
409
ACTIVATION_IN_PROGRESS
Another activation request is currently processing this txHash. Retry after a brief pause.
429
(no code)
Rate limit exceeded for the IP or API key, OR no TX credits remaining (purchase additional credits).
500
ACTIVATION_RETRY
Activation failed during the KV write phase. Retry — the operation is idempotent, so a second attempt will pick up where the first stopped.

FAQ

Do users need BNB, ETH, or AVAX to use Q402?
No. Users only need USDC (or USDT) in their wallet. All gas is paid from your gas pool. The user signs a message — that's it.
Who pays the gas fees?
You do — from your gas pool. You deposit native tokens (BNB on BNB Chain, ETH on Ethereum, etc.) to your project's gas pool address. Q402 auto-deducts the exact gas cost per transaction. To withdraw, contact business@quackai.ai — withdrawals are processed manually by Q402 operations.
Is Q402 non-custodial?
Yes. Q402 never holds user funds. The EIP-712 signature authorizes exactly one transfer from A to C. Q402 only pays gas and relays — it cannot redirect or intercept USDC.
What if a transaction fails?
If relay fails, the payload is discarded and no user funds are moved. Check the error code in the API response — common causes are insufficient gas tank balance or an expired deadline.
Can I use Q402 with tokens other than USDC?
Currently USDC and USDT are supported on every live chain except Injective EVM, which is USDT-only at launch — native USDC via Circle CCTP is announced for Q2 2026 and will be added in the next minor release. Additional ERC-20 token support is on the roadmap.
How do I get an API key?
Connect your wallet on the dashboard — a sandbox API key (q402_test_ prefix) is provisioned for free so you can test the integration. To get a live key, complete an on-chain payment on the /payment page. Your live key is issued automatically after the payment is confirmed.
How does billing work? Can I upgrade my plan?
Each paid purchase grants a 30-day access window plus the transaction credits listed for that tier. Your plan tier is set by cumulative paid amount within the active window, normalized to BNB Chain base pricing (Ethereum and Avalanche are converted at the chain multiplier). Top up within 30 days and your plan upgrades automatically when cumulative spend crosses the next tier. Plans never downgrade while the window is active; if you let the window lapse, cumulative resets.

Ready to go gasless?

Pick a plan, send an on-chain payment, and your live API key is issued automatically. Sandbox key available for free to test first.