Qiguard API docs

Quickstart

From sign-in to a first swap on Base. Allow a few minutes, plus the time until your app is approved.

Your own fee per trade: add swapFeeRecipient and swapFeeBps to price and quote (see Swap). Not in v1: exact-out (buyAmount) and the /swap/permit2/* endpoints.

1. Sign in and create an app

  1. Open dashboard.qiguard.com and choose Continue with MetaMask. Complete the human check, then sign the sign-in message in MetaMask. Signing sends no transaction and costs no gas.
  2. Enter your team name and project type (wallet, DEX, bot, platform or other). A contact email is optional.
  3. Create an app: give it a name, pick the products (swap, gasless) and the chains.
  4. The app starts as pending. Keys of a pending app answer 403 APP_NOT_APPROVED; they work as soon as the app is approved. Adding a product or a chain to an approved app later sends it back for review.

2. Create a key

Open the app, tab Keys, and choose Create key. The key (qg_sk_...) is shown once: copy it into your server's secret store. Qiguard keeps only a keyed hash of it.

Secret keys are for servers. A secret key sent by a browser (an Origin header together with Sec-Fetch-Mode: cors) is refused with 403 ORIGIN_NOT_ALLOWED.

3. First calls

Keyless calls need no header:

curl -s https://api.qiguard.com/swap/chains
curl -s "https://api.qiguard.com/tokens?chainId=8453"

A price for 25 USDC to WETH on Base:

curl -s "https://api.qiguard.com/swap/allowance-holder/price?chainId=8453&sellToken=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&buyToken=0x4200000000000000000000000000000000000006&sellAmount=25000000" \
  -H "qg-api-key: $QG_API_KEY" -H "qg-version: v1"

buyAmount and minBuyAmount are net amounts, after the on-chain fee in fees.qiguardFee.

4. Install the SDK

The JavaScript SDK is one file with no dependencies (Node 18+, Workers, browsers for keyless calls). Download it, with its type declarations, next to your code:

curl -sO https://docs.qiguard.com/sdk/qiguard-sdk.mjs
curl -sO https://docs.qiguard.com/sdk/qiguard-sdk.d.ts
FileSHA-256
qiguard-sdk.mjsa444094cbd4d19133b9e3e801a75b284f68aead5b825fb72cfdc8de744583459
qiguard-sdk.d.tsb5b6b75341b9e514e4e3b14673b6e4f4881e2a2ad95554a3fb2477aeebd1e963

Then import it by path: import { QiguardClient } from './qiguard-sdk.mjs';.

5. Quote, approve, send

  1. Call GET /swap/allowance-holder/quote with the same parameters plus taker (the wallet that sends the trade).
  2. If issues.allowance is set, the taker approves issues.allowance.spender (the settlement contract) for exactly sellAmount, and waits for the approval receipt.
  3. Quote again: the transaction carries a deadline (expiresAt, 120 seconds by default).
  4. Check that transaction.to is the settlement contract of the chain (Contracts and fees), then send transaction as returned: to, data, value, and gas as the gas limit.

With the SDK and viem (npm install viem; TAKER_KEY is the private key of the trading wallet, kept in your own secret store):

import { createWalletClient, createPublicClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
import { QiguardClient, approvalsForQuote, assertSwapQuote } from './qiguard-sdk.mjs';

const account = privateKeyToAccount(process.env.TAKER_KEY); // your wallet
const wallet = createWalletClient({ account, chain: base, transport: http() });
const reader = createPublicClient({ chain: base, transport: http() });
const sendAndWait = async (tx) => {
  const hash = await wallet.sendTransaction({ to: tx.to, data: tx.data, value: BigInt(tx.value), gas: tx.gas ? BigInt(tx.gas) : undefined });
  return reader.waitForTransactionReceipt({ hash });
};

const qg = new QiguardClient({ apiKey: process.env.QG_API_KEY });
const taker = account.address;
const params = {
  chainId: 8453,
  sellToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC
  buyToken: '0x4200000000000000000000000000000000000006',  // WETH
  sellAmount: '25000000',
  taker,
};

let quote = await qg.getQuote(params);
// exact-amount approvals, only ever for the settlement contract pinned in the SDK
for (const tx of approvalsForQuote(quote, { chainId: params.chainId })) await sendAndWait(tx);
quote = await qg.getQuote(params);
assertSwapQuote(quote, { chainId: params.chainId, sellToken: params.sellToken, buyToken: params.buyToken, sellAmount: params.sellAmount });
const receipt = await sendAndWait(quote.transaction);
console.log(receipt.status, receipt.transactionHash);

Complete scripts: swap-viem.mjs (this flow) and gasless-viem.mjs (gasless, with the checks before signing). They import ./qiguard-sdk.mjs from the same folder.

6. Check the dashboard

The Usage tab of the app shows requests per hour, errors and latency per endpoint. The Audit log lists sign-ins, key changes and app decisions.

Next