# API reference

Built from the OpenAPI 3.1.0 document of the Qiguard API, version 1.0.0. Download it as [openapi.yaml](openapi.yaml) or [openapi.json](openapi.json).

Base URL `https://api.qiguard.com`. Keyed endpoints need the headers `qg-api-key` and `qg-version: v1`; keyless endpoints need no header. Every response carries the header `qg-zid` and the body field `zid`.

## Endpoints

| Method | Path | Key | Summary |
|---|---|---|---|
| GET | [`/swap/allowance-holder/price`](#get-swap-allowance-holder-price) | yes | Indicative price for an allowance-holder swap |
| GET | [`/swap/allowance-holder/quote`](#get-swap-allowance-holder-quote) | yes | Firm quote with the transaction to send |
| GET | [`/gasless/price`](#get-gasless-price) | yes | Indicative price for a gasless swap |
| GET | [`/gasless/quote`](#get-gasless-quote) | yes | Gasless quote with the Permit2 witness message to sign |
| POST | [`/gasless/submit`](#post-gasless-submit) | yes | Submit a signed gasless trade |
| GET | [`/gasless/status/{tradeHash}`](#get-gasless-status-tradehash) | yes | Status of a submitted gasless trade |
| GET | [`/swap/chains`](#get-swap-chains) | no | Chains supported by the Swap endpoints |
| GET | [`/gasless/chains`](#get-gasless-chains) | no | Chains supported by the Gasless endpoints |
| GET | [`/sources`](#get-sources) | no | Liquidity sources of a chain (names usable in excludedSources) |
| GET | [`/tokens`](#get-tokens) | no | Tokens and anchors supported on a chain |
| GET | [`/status`](#get-status) | no | Live state of every chain (contract pause flag, RPC, swap and gasless availability) |

## GET /swap/allowance-holder/price

Indicative price for an allowance-holder swap.

- Key: API key (`qg-api-key`) and `qg-version: v1`
- Endpoint id: `swap.price` (the name used in the dashboard usage tables)
- Operation id: `swap_allowanceholderGetPrice`

### Parameters of GET /swap/allowance-holder/price

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `qg-version` | header | yes | string, one of `v1` | API version. Missing gives `400 API_VERSION_MISSING`; another value gives `400 INPUT_INVALID`. |
| `chainId` | query | yes | integer, one of `1`, `56`, `137`, `8453` |  |
| `sellToken` | query | yes | [Address](#schema-address) |  |
| `buyToken` | query | yes | [Address](#schema-address) |  |
| `sellAmount` | query | yes | [Uint](#schema-uint) | Amount of sellToken in base units. |
| `buyAmount` | query | no | [Uint](#schema-uint) | Exact-out is not supported in v1; sending it gives `400 EXACT_OUT_NOT_SUPPORTED`. (not used in v1) |
| `taker` | query | no | [Address](#schema-address) | The wallet that holds sellToken. When present, `issues` are filled and the wallet's on-chain fee rate is used. |
| `recipient` | query | no | [Address](#schema-address) | Must be absent or equal to `taker`; otherwise `400 RECIPIENT_NOT_SUPPORTED` (the contract pays the taker). |
| `slippageBps` | query | no | integer, 10 to 1000, default `100` | Default 100, allowed 10-1000. Mutually exclusive with slippagePpm. `minBuyAmount = floor(buyAmount * (10000 - slippageBps) / 10000)`. |
| `slippagePpm` | query | no | integer, 1000 to 100000 | Slippage in parts per million, rounded down to whole bps (warning `slippage_ppm_rounded`). Same limits as slippageBps. |
| `deadlineSeconds` | query | no | integer, 30 to 600, default `120` | Seconds until the calldata deadline (`expiresAt`). Default 120, allowed 30-600. |
| `excludedSources` | query | no | string | Comma-separated names from `/sources`. Unknown names are listed in `issues.invalidSourcesPassed`. |
| `gasPrice` | query | no | [Uint](#schema-uint) | Gas price in wei for the estimate. Default is the chain's current gas price. |
| `swapFeeRecipient` | query | no | string | Your fee wallet, or up to 3 wallets separated by commas. Sent together with swapFeeBps; the router pays each wallet its share on chain in the same transaction. |
| `swapFeeBps` | query | no | string | The fee of each swapFeeRecipient in basis points, in the same order (for example `30` or `20,10`). The total is at most 300. |
| `swapFeePpm` | query | no | string | Not accepted (`400 INPUT_INVALID`); use swapFeeBps. (not used in v1) |
| `swapFeeToken` | query | no | [Address](#schema-address) | The token the integrator fee is taken in, sellToken or buyToken. Default buyToken. |
| `tradeSurplusRecipient` | query | no | string | Accepted and ignored (warning `trade_surplus_ignored`); the whole output always goes to the taker. (not used in v1) |
| `tradeSurplusMaxBps` | query | no | string | Accepted and ignored (warning `trade_surplus_ignored`). (not used in v1) |
| `tradeSurplusMaxPpm` | query | no | string | Accepted and ignored (warning `trade_surplus_ignored`). (not used in v1) |
| `txOrigin` | query | no | [Address](#schema-address) | Accepted and ignored (warning `tx_origin_ignored`). The contract pays msg.sender, so a contract taker must call the contract itself. (not used in v1) |
| `sellEntireBalance` | query | no | string, one of `true`, `false` | `false` is accepted; `true` gives `400 INPUT_INVALID` (reason `not_supported`). |
| `wrapUnwrapMode` | query | no | string, one of `direct`, `settler` | `direct` is accepted and ignored; `settler` gives `400 INPUT_INVALID`. Wrap and unwrap pairs give `TOKEN_PAIR_NOT_SUPPORTED`. |

### Responses of GET /swap/allowance-holder/price

| Status | Meaning | Body |
|---|---|---|
| 200 | A price, or `liquidityAvailable false` when no route exists. | [SwapPrice](#schema-swapprice) or [NoLiquidity](#schema-noliquidity) |
| 400 | INPUT_INVALID, HTTPS_REQUIRED, API_VERSION_MISSING, CHAIN_NOT_SUPPORTED, TOKEN_NOT_SUPPORTED, TOKEN_PAIR_NOT_SUPPORTED, RECIPIENT_NOT_SUPPORTED, SELL_AMOUNT_TOO_SMALL, INSUFFICIENT_BALANCE (gasless quote only), SWAP_VALIDATION_FAILED, UNABLE_TO_CALCULATE_GAS_FEE, SMART_WALLET_NOT_SUPPORTED, INTEGRATOR_FEE_NOT_SUPPORTED, EXACT_OUT_NOT_SUPPORTED, IDEMPOTENCY_KEY_REUSED; on submit also INSUFFICIENT_BALANCE_OR_ALLOWANCE, INVALID_APPROVAL, INVALID_SIGNATURE, INVALID_SIGNER, META_TRANSACTION_EXPIRY_TOO_SOON, META_TRANSACTION_INVALID, PENDING_TRADES_ALREADY_EXIST, TRADE_ALREADY_SUBMITTED. | [Error](#schema-error) |
| 401 | API_KEY_MISSING (message "No API key found in request") or API_KEY_INVALID (unknown, malformed or revoked key). | [Error](#schema-error) |
| 403 | APP_NOT_APPROVED (data.status pending or suspended), PRODUCT_NOT_ENABLED (data.reason product_not_enabled or chain_not_enabled), ORIGIN_NOT_ALLOWED, TAKER_NOT_AUTHORIZED_FOR_TRADE (data.reason denied or gasless_blocked). | [Error](#schema-error) |
| 429 | RATE_LIMITED (Retry-After 10), QUOTA_EXCEEDED (daily request cap or gasless submits per day; Retry-After = seconds to 00:00 UTC), GAS_BUDGET_EXCEEDED (sponsored-gas budget of the app, the chain or the free tier). | [Error](#schema-error) |
| 500 | INTERNAL_SERVER_ERROR or UNCATEGORIZED. | [Error](#schema-error) |
| 503 | SETTLEMENT_PAUSED (contract paused), SWAP_NOT_ENABLED (swap switched off for the chain), GASLESS_NOT_ENABLED (data.reason gasless_not_enabled: relayer not set up or funded yet, or switched off), RELAYER_UNAVAILABLE (data.reason relayer_low_balance, relayer_busy, relayer_stalled, gas_price_above_cap, relayer_timeout or relayer_unreachable; Retry-After when busy or timed out; relayer_timeout and relayer_unreachable add data.tradeHash: read the status of that trade before quoting again), RPC_UNAVAILABLE. | [Error](#schema-error) |

```sh
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"
```

## GET /swap/allowance-holder/quote

Firm quote with the transaction to send.

Same parameters as the price endpoint; `taker` is required. `transaction.data` calls `marketSwap`,
`marketSwapNativeToToken` or `marketSwapTokenToNative` on the settlement contract, followed by the 18-byte
Qiguard tag (`qiguard.tag`). Approve `issues.allowance.spender` for the exact `sellAmount`, wait for the
approval receipt, then quote again: `transaction` expires at `expiresAt`.

- Key: API key (`qg-api-key`) and `qg-version: v1`
- Endpoint id: `swap.quote` (the name used in the dashboard usage tables)
- Operation id: `swap_allowanceholderGetQuote`

### Parameters of GET /swap/allowance-holder/quote

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `qg-version` | header | yes | string, one of `v1` | API version. Missing gives `400 API_VERSION_MISSING`; another value gives `400 INPUT_INVALID`. |
| `chainId` | query | yes | integer, one of `1`, `56`, `137`, `8453` |  |
| `sellToken` | query | yes | [Address](#schema-address) |  |
| `buyToken` | query | yes | [Address](#schema-address) |  |
| `sellAmount` | query | yes | [Uint](#schema-uint) | Amount of sellToken in base units. |
| `buyAmount` | query | no | [Uint](#schema-uint) | Exact-out is not supported in v1; sending it gives `400 EXACT_OUT_NOT_SUPPORTED`. (not used in v1) |
| `taker` | query | yes | [Address](#schema-address) | The wallet that holds sellToken and sends (or signs) the trade. |
| `recipient` | query | no | [Address](#schema-address) | Must be absent or equal to `taker`; otherwise `400 RECIPIENT_NOT_SUPPORTED` (the contract pays the taker). |
| `slippageBps` | query | no | integer, 10 to 1000, default `100` | Default 100, allowed 10-1000. Mutually exclusive with slippagePpm. `minBuyAmount = floor(buyAmount * (10000 - slippageBps) / 10000)`. |
| `slippagePpm` | query | no | integer, 1000 to 100000 | Slippage in parts per million, rounded down to whole bps (warning `slippage_ppm_rounded`). Same limits as slippageBps. |
| `deadlineSeconds` | query | no | integer, 30 to 600, default `120` | Seconds until the calldata deadline (`expiresAt`). Default 120, allowed 30-600. |
| `excludedSources` | query | no | string | Comma-separated names from `/sources`. Unknown names are listed in `issues.invalidSourcesPassed`. |
| `gasPrice` | query | no | [Uint](#schema-uint) | Gas price in wei for the estimate. Default is the chain's current gas price. |
| `swapFeeRecipient` | query | no | string | Your fee wallet, or up to 3 wallets separated by commas. Sent together with swapFeeBps; the router pays each wallet its share on chain in the same transaction. |
| `swapFeeBps` | query | no | string | The fee of each swapFeeRecipient in basis points, in the same order (for example `30` or `20,10`). The total is at most 300. |
| `swapFeePpm` | query | no | string | Not accepted (`400 INPUT_INVALID`); use swapFeeBps. (not used in v1) |
| `swapFeeToken` | query | no | [Address](#schema-address) | The token the integrator fee is taken in, sellToken or buyToken. Default buyToken. |
| `tradeSurplusRecipient` | query | no | string | Accepted and ignored (warning `trade_surplus_ignored`); the whole output always goes to the taker. (not used in v1) |
| `tradeSurplusMaxBps` | query | no | string | Accepted and ignored (warning `trade_surplus_ignored`). (not used in v1) |
| `tradeSurplusMaxPpm` | query | no | string | Accepted and ignored (warning `trade_surplus_ignored`). (not used in v1) |
| `txOrigin` | query | no | [Address](#schema-address) | Accepted and ignored (warning `tx_origin_ignored`). The contract pays msg.sender, so a contract taker must call the contract itself. (not used in v1) |
| `sellEntireBalance` | query | no | string, one of `true`, `false` | `false` is accepted; `true` gives `400 INPUT_INVALID` (reason `not_supported`). |
| `wrapUnwrapMode` | query | no | string, one of `direct`, `settler` | `direct` is accepted and ignored; `settler` gives `400 INPUT_INVALID`. Wrap and unwrap pairs give `TOKEN_PAIR_NOT_SUPPORTED`. |

### Responses of GET /swap/allowance-holder/quote

| Status | Meaning | Body |
|---|---|---|
| 200 | A quote, or `liquidityAvailable false` when no route exists. | [SwapQuote](#schema-swapquote) or [NoLiquidity](#schema-noliquidity) |
| 400 | INPUT_INVALID, HTTPS_REQUIRED, API_VERSION_MISSING, CHAIN_NOT_SUPPORTED, TOKEN_NOT_SUPPORTED, TOKEN_PAIR_NOT_SUPPORTED, RECIPIENT_NOT_SUPPORTED, SELL_AMOUNT_TOO_SMALL, INSUFFICIENT_BALANCE (gasless quote only), SWAP_VALIDATION_FAILED, UNABLE_TO_CALCULATE_GAS_FEE, SMART_WALLET_NOT_SUPPORTED, INTEGRATOR_FEE_NOT_SUPPORTED, EXACT_OUT_NOT_SUPPORTED, IDEMPOTENCY_KEY_REUSED; on submit also INSUFFICIENT_BALANCE_OR_ALLOWANCE, INVALID_APPROVAL, INVALID_SIGNATURE, INVALID_SIGNER, META_TRANSACTION_EXPIRY_TOO_SOON, META_TRANSACTION_INVALID, PENDING_TRADES_ALREADY_EXIST, TRADE_ALREADY_SUBMITTED. | [Error](#schema-error) |
| 401 | API_KEY_MISSING (message "No API key found in request") or API_KEY_INVALID (unknown, malformed or revoked key). | [Error](#schema-error) |
| 403 | APP_NOT_APPROVED (data.status pending or suspended), PRODUCT_NOT_ENABLED (data.reason product_not_enabled or chain_not_enabled), ORIGIN_NOT_ALLOWED, TAKER_NOT_AUTHORIZED_FOR_TRADE (data.reason denied or gasless_blocked). | [Error](#schema-error) |
| 429 | RATE_LIMITED (Retry-After 10), QUOTA_EXCEEDED (daily request cap or gasless submits per day; Retry-After = seconds to 00:00 UTC), GAS_BUDGET_EXCEEDED (sponsored-gas budget of the app, the chain or the free tier). | [Error](#schema-error) |
| 500 | INTERNAL_SERVER_ERROR or UNCATEGORIZED. | [Error](#schema-error) |
| 503 | SETTLEMENT_PAUSED (contract paused), SWAP_NOT_ENABLED (swap switched off for the chain), GASLESS_NOT_ENABLED (data.reason gasless_not_enabled: relayer not set up or funded yet, or switched off), RELAYER_UNAVAILABLE (data.reason relayer_low_balance, relayer_busy, relayer_stalled, gas_price_above_cap, relayer_timeout or relayer_unreachable; Retry-After when busy or timed out; relayer_timeout and relayer_unreachable add data.tradeHash: read the status of that trade before quoting again), RPC_UNAVAILABLE. | [Error](#schema-error) |

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

The example taker `0x1111111111111111111111111111111111111111` is a placeholder: replace it with your wallet address.

## GET /gasless/price

Indicative price for a gasless swap.

ERC-20 to ERC-20 only (the wrapped native token is allowed, the native coin is not). On a chain listed by
`/gasless/chains` with `enabled: false` the price is still returned, with the warning `gasless_not_enabled`.
With a `taker` whose balance is below `sellAmount`, the price is still returned and `issues.balance` shows
the shortfall; only `/gasless/quote` answers `400 INSUFFICIENT_BALANCE`.

- Key: API key (`qg-api-key`) and `qg-version: v1`
- Endpoint id: `gasless.price` (the name used in the dashboard usage tables)
- Operation id: `gasless_getPrice`

### Parameters of GET /gasless/price

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `qg-version` | header | yes | string, one of `v1` | API version. Missing gives `400 API_VERSION_MISSING`; another value gives `400 INPUT_INVALID`. |
| `chainId` | query | yes | integer, one of `56`, `8453` | Gasless chains are BSC (56) and Base (8453). Other values give `400 CHAIN_NOT_SUPPORTED`. |
| `sellToken` | query | yes | [Address](#schema-address) |  |
| `buyToken` | query | yes | [Address](#schema-address) |  |
| `sellAmount` | query | yes | [Uint](#schema-uint) | Amount of sellToken in base units. |
| `buyAmount` | query | no | [Uint](#schema-uint) | Exact-out is not supported in v1; sending it gives `400 EXACT_OUT_NOT_SUPPORTED`. (not used in v1) |
| `taker` | query | no | [Address](#schema-address) | The wallet that holds sellToken. When present, `issues` are filled and the wallet's on-chain fee rate is used. |
| `recipient` | query | no | [Address](#schema-address) | Must be absent or equal to `taker`; otherwise `400 RECIPIENT_NOT_SUPPORTED` (the contract pays the taker). |
| `slippageBps` | query | no | integer, 10 to 300, default `50` | Default 50, allowed 10-300. Mutually exclusive with slippagePpm. |
| `slippagePpm` | query | no | integer, 1000 to 100000 | Slippage in parts per million, rounded down to whole bps (warning `slippage_ppm_rounded`). Same limits as slippageBps. |
| `deadlineSeconds` | query | no | integer, 60 to 600, default `180` | Seconds until the signed deadline. Default 180, allowed 60-600. |
| `excludedSources` | query | no | string | Comma-separated names from `/sources`. Unknown names are listed in `issues.invalidSourcesPassed`. |
| `swapFeeRecipient` | query | no | string | Your fee wallet, or up to 3 wallets separated by commas. Sent together with swapFeeBps; the router pays each wallet its share on chain in the same transaction. |
| `swapFeeBps` | query | no | string | The fee of each swapFeeRecipient in basis points, in the same order (for example `30` or `20,10`). The total is at most 300. |
| `swapFeePpm` | query | no | string | Not accepted (`400 INPUT_INVALID`); use swapFeeBps. (not used in v1) |
| `swapFeeToken` | query | no | [Address](#schema-address) | The token the integrator fee is taken in, sellToken or buyToken. Default buyToken. |
| `tradeSurplusRecipient` | query | no | string | Accepted and ignored (warning `trade_surplus_ignored`); the whole output always goes to the taker. (not used in v1) |
| `tradeSurplusMaxBps` | query | no | string | Accepted and ignored (warning `trade_surplus_ignored`). (not used in v1) |
| `tradeSurplusMaxPpm` | query | no | string | Accepted and ignored (warning `trade_surplus_ignored`). (not used in v1) |

### Responses of GET /gasless/price

| Status | Meaning | Body |
|---|---|---|
| 200 | A gasless price, or `liquidityAvailable false`. | [GaslessPrice](#schema-gaslessprice) or [NoLiquidity](#schema-noliquidity) |
| 400 | INPUT_INVALID, HTTPS_REQUIRED, API_VERSION_MISSING, CHAIN_NOT_SUPPORTED, TOKEN_NOT_SUPPORTED, TOKEN_PAIR_NOT_SUPPORTED, RECIPIENT_NOT_SUPPORTED, SELL_AMOUNT_TOO_SMALL, INSUFFICIENT_BALANCE (gasless quote only), SWAP_VALIDATION_FAILED, UNABLE_TO_CALCULATE_GAS_FEE, SMART_WALLET_NOT_SUPPORTED, INTEGRATOR_FEE_NOT_SUPPORTED, EXACT_OUT_NOT_SUPPORTED, IDEMPOTENCY_KEY_REUSED; on submit also INSUFFICIENT_BALANCE_OR_ALLOWANCE, INVALID_APPROVAL, INVALID_SIGNATURE, INVALID_SIGNER, META_TRANSACTION_EXPIRY_TOO_SOON, META_TRANSACTION_INVALID, PENDING_TRADES_ALREADY_EXIST, TRADE_ALREADY_SUBMITTED. | [Error](#schema-error) |
| 401 | API_KEY_MISSING (message "No API key found in request") or API_KEY_INVALID (unknown, malformed or revoked key). | [Error](#schema-error) |
| 403 | APP_NOT_APPROVED (data.status pending or suspended), PRODUCT_NOT_ENABLED (data.reason product_not_enabled or chain_not_enabled), ORIGIN_NOT_ALLOWED, TAKER_NOT_AUTHORIZED_FOR_TRADE (data.reason denied or gasless_blocked). | [Error](#schema-error) |
| 429 | RATE_LIMITED (Retry-After 10), QUOTA_EXCEEDED (daily request cap or gasless submits per day; Retry-After = seconds to 00:00 UTC), GAS_BUDGET_EXCEEDED (sponsored-gas budget of the app, the chain or the free tier). | [Error](#schema-error) |
| 500 | INTERNAL_SERVER_ERROR or UNCATEGORIZED. | [Error](#schema-error) |
| 503 | SETTLEMENT_PAUSED (contract paused), SWAP_NOT_ENABLED (swap switched off for the chain), GASLESS_NOT_ENABLED (data.reason gasless_not_enabled: relayer not set up or funded yet, or switched off), RELAYER_UNAVAILABLE (data.reason relayer_low_balance, relayer_busy, relayer_stalled, gas_price_above_cap, relayer_timeout or relayer_unreachable; Retry-After when busy or timed out; relayer_timeout and relayer_unreachable add data.tradeHash: read the status of that trade before quoting again), RPC_UNAVAILABLE. | [Error](#schema-error) |

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

## GET /gasless/quote

Gasless quote with the Permit2 witness message to sign.

`taker` is required. Sign `trade.eip712` with `eth_signTypedData_v4` and send it to `POST /gasless/submit`.
`approval` is always `null` in v1: a taker without a Permit2 allowance must first send one normal
`approve(Permit2, amount)` transaction and pay its gas (`issues.allowance` shows it). A taker balance below
`sellAmount` gives `400 INSUFFICIENT_BALANCE`. Before signing, check that `domain.verifyingContract` is Permit2,
`message.spender` is the settlement contract of the chain and `witness.recipient` is the taker (the SDK's
`assertGaslessTrade` does this).

- Key: API key (`qg-api-key`) and `qg-version: v1`
- Endpoint id: `gasless.quote` (the name used in the dashboard usage tables)
- Operation id: `gasless_getQuote`

### Parameters of GET /gasless/quote

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `qg-version` | header | yes | string, one of `v1` | API version. Missing gives `400 API_VERSION_MISSING`; another value gives `400 INPUT_INVALID`. |
| `chainId` | query | yes | integer, one of `56`, `8453` | Gasless chains are BSC (56) and Base (8453). Other values give `400 CHAIN_NOT_SUPPORTED`. |
| `sellToken` | query | yes | [Address](#schema-address) |  |
| `buyToken` | query | yes | [Address](#schema-address) |  |
| `sellAmount` | query | yes | [Uint](#schema-uint) | Amount of sellToken in base units. |
| `buyAmount` | query | no | [Uint](#schema-uint) | Exact-out is not supported in v1; sending it gives `400 EXACT_OUT_NOT_SUPPORTED`. (not used in v1) |
| `taker` | query | yes | [Address](#schema-address) | The wallet that holds sellToken and sends (or signs) the trade. |
| `recipient` | query | no | [Address](#schema-address) | Must be absent or equal to `taker`; otherwise `400 RECIPIENT_NOT_SUPPORTED` (the contract pays the taker). |
| `slippageBps` | query | no | integer, 10 to 300, default `50` | Default 50, allowed 10-300. Mutually exclusive with slippagePpm. |
| `slippagePpm` | query | no | integer, 1000 to 100000 | Slippage in parts per million, rounded down to whole bps (warning `slippage_ppm_rounded`). Same limits as slippageBps. |
| `deadlineSeconds` | query | no | integer, 60 to 600, default `180` | Seconds until the signed deadline. Default 180, allowed 60-600. |
| `excludedSources` | query | no | string | Comma-separated names from `/sources`. Unknown names are listed in `issues.invalidSourcesPassed`. |
| `swapFeeRecipient` | query | no | string | Your fee wallet, or up to 3 wallets separated by commas. Sent together with swapFeeBps; the router pays each wallet its share on chain in the same transaction. |
| `swapFeeBps` | query | no | string | The fee of each swapFeeRecipient in basis points, in the same order (for example `30` or `20,10`). The total is at most 300. |
| `swapFeePpm` | query | no | string | Not accepted (`400 INPUT_INVALID`); use swapFeeBps. (not used in v1) |
| `swapFeeToken` | query | no | [Address](#schema-address) | The token the integrator fee is taken in, sellToken or buyToken. Default buyToken. |
| `tradeSurplusRecipient` | query | no | string | Accepted and ignored (warning `trade_surplus_ignored`); the whole output always goes to the taker. (not used in v1) |
| `tradeSurplusMaxBps` | query | no | string | Accepted and ignored (warning `trade_surplus_ignored`). (not used in v1) |
| `tradeSurplusMaxPpm` | query | no | string | Accepted and ignored (warning `trade_surplus_ignored`). (not used in v1) |

### Responses of GET /gasless/quote

| Status | Meaning | Body |
|---|---|---|
| 200 | A gasless quote, or `liquidityAvailable false`. | [GaslessQuote](#schema-gaslessquote) or [NoLiquidity](#schema-noliquidity) |
| 400 | INPUT_INVALID, HTTPS_REQUIRED, API_VERSION_MISSING, CHAIN_NOT_SUPPORTED, TOKEN_NOT_SUPPORTED, TOKEN_PAIR_NOT_SUPPORTED, RECIPIENT_NOT_SUPPORTED, SELL_AMOUNT_TOO_SMALL, INSUFFICIENT_BALANCE (gasless quote only), SWAP_VALIDATION_FAILED, UNABLE_TO_CALCULATE_GAS_FEE, SMART_WALLET_NOT_SUPPORTED, INTEGRATOR_FEE_NOT_SUPPORTED, EXACT_OUT_NOT_SUPPORTED, IDEMPOTENCY_KEY_REUSED; on submit also INSUFFICIENT_BALANCE_OR_ALLOWANCE, INVALID_APPROVAL, INVALID_SIGNATURE, INVALID_SIGNER, META_TRANSACTION_EXPIRY_TOO_SOON, META_TRANSACTION_INVALID, PENDING_TRADES_ALREADY_EXIST, TRADE_ALREADY_SUBMITTED. | [Error](#schema-error) |
| 401 | API_KEY_MISSING (message "No API key found in request") or API_KEY_INVALID (unknown, malformed or revoked key). | [Error](#schema-error) |
| 403 | APP_NOT_APPROVED (data.status pending or suspended), PRODUCT_NOT_ENABLED (data.reason product_not_enabled or chain_not_enabled), ORIGIN_NOT_ALLOWED, TAKER_NOT_AUTHORIZED_FOR_TRADE (data.reason denied or gasless_blocked). | [Error](#schema-error) |
| 429 | RATE_LIMITED (Retry-After 10), QUOTA_EXCEEDED (daily request cap or gasless submits per day; Retry-After = seconds to 00:00 UTC), GAS_BUDGET_EXCEEDED (sponsored-gas budget of the app, the chain or the free tier). | [Error](#schema-error) |
| 500 | INTERNAL_SERVER_ERROR or UNCATEGORIZED. | [Error](#schema-error) |
| 503 | SETTLEMENT_PAUSED (contract paused), SWAP_NOT_ENABLED (swap switched off for the chain), GASLESS_NOT_ENABLED (data.reason gasless_not_enabled: relayer not set up or funded yet, or switched off), RELAYER_UNAVAILABLE (data.reason relayer_low_balance, relayer_busy, relayer_stalled, gas_price_above_cap, relayer_timeout or relayer_unreachable; Retry-After when busy or timed out; relayer_timeout and relayer_unreachable add data.tradeHash: read the status of that trade before quoting again), RPC_UNAVAILABLE. | [Error](#schema-error) |

```sh
curl -s "https://api.qiguard.com/gasless/quote?chainId=8453&sellToken=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&buyToken=0x4200000000000000000000000000000000000006&sellAmount=25000000&taker=0x1111111111111111111111111111111111111111" \
  -H "qg-api-key: $QG_API_KEY" -H "qg-version: v1"
```

The example taker `0x1111111111111111111111111111111111111111` is a placeholder: replace it with your wallet address.

## POST /gasless/submit

Submit a signed gasless trade.

Idempotent by `tradeHash` (the EIP-712 digest): the same trade from the same app returns `200` with the same
body; from another app it returns `400 TRADE_ALREADY_SUBMITTED`. An optional `Idempotency-Key` header is also
honoured for 24 hours. Until gasless is enabled on the chain (relayer funded and switched on), this endpoint
returns `503 GASLESS_NOT_ENABLED` with `data.reason = "gasless_not_enabled"`.
A `503 RELAYER_UNAVAILABLE` with `data.reason` `relayer_timeout` or `relayer_unreachable` carries
`data.tradeHash`: the trade may still have been accepted, so read `GET /gasless/status/{tradeHash}` (404 means
it was not) before quoting and signing again; sending the same body again returns the earlier answer.

- Key: API key (`qg-api-key`) and `qg-version: v1`
- Endpoint id: `gasless.submit` (the name used in the dashboard usage tables)
- Operation id: `gasless_submit`

### Parameters of POST /gasless/submit

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `qg-version` | header | yes | string, one of `v1` | API version. Missing gives `400 API_VERSION_MISSING`; another value gives `400 INPUT_INVALID`. |
| `Idempotency-Key` | header | no | string, pattern `^[\x21-\x7e]{1,64}$`, length 1 to 64 | 1-64 visible ASCII characters. Same key and same body within 24 h returns the stored response; same key with another body gives `400 IDEMPOTENCY_KEY_REUSED`. |

### Request body of POST /gasless/submit

JSON, required: [GaslessSubmitRequest](#schema-gaslesssubmitrequest).

### Responses of POST /gasless/submit

| Status | Meaning | Body |
|---|---|---|
| 200 | Accepted (status `pending`), or the earlier result of the same trade. | [GaslessSubmitResponse](#schema-gaslesssubmitresponse) |
| 400 | INPUT_INVALID, HTTPS_REQUIRED, API_VERSION_MISSING, CHAIN_NOT_SUPPORTED, TOKEN_NOT_SUPPORTED, TOKEN_PAIR_NOT_SUPPORTED, RECIPIENT_NOT_SUPPORTED, SELL_AMOUNT_TOO_SMALL, INSUFFICIENT_BALANCE (gasless quote only), SWAP_VALIDATION_FAILED, UNABLE_TO_CALCULATE_GAS_FEE, SMART_WALLET_NOT_SUPPORTED, INTEGRATOR_FEE_NOT_SUPPORTED, EXACT_OUT_NOT_SUPPORTED, IDEMPOTENCY_KEY_REUSED; on submit also INSUFFICIENT_BALANCE_OR_ALLOWANCE, INVALID_APPROVAL, INVALID_SIGNATURE, INVALID_SIGNER, META_TRANSACTION_EXPIRY_TOO_SOON, META_TRANSACTION_INVALID, PENDING_TRADES_ALREADY_EXIST, TRADE_ALREADY_SUBMITTED. | [Error](#schema-error) |
| 401 | API_KEY_MISSING (message "No API key found in request") or API_KEY_INVALID (unknown, malformed or revoked key). | [Error](#schema-error) |
| 403 | APP_NOT_APPROVED (data.status pending or suspended), PRODUCT_NOT_ENABLED (data.reason product_not_enabled or chain_not_enabled), ORIGIN_NOT_ALLOWED, TAKER_NOT_AUTHORIZED_FOR_TRADE (data.reason denied or gasless_blocked). | [Error](#schema-error) |
| 413 | PAYLOAD_TOO_LARGE (body above 256 KB). | [Error](#schema-error) |
| 429 | RATE_LIMITED (Retry-After 10), QUOTA_EXCEEDED (daily request cap or gasless submits per day; Retry-After = seconds to 00:00 UTC), GAS_BUDGET_EXCEEDED (sponsored-gas budget of the app, the chain or the free tier). | [Error](#schema-error) |
| 500 | INTERNAL_SERVER_ERROR or UNCATEGORIZED. | [Error](#schema-error) |
| 503 | SETTLEMENT_PAUSED (contract paused), SWAP_NOT_ENABLED (swap switched off for the chain), GASLESS_NOT_ENABLED (data.reason gasless_not_enabled: relayer not set up or funded yet, or switched off), RELAYER_UNAVAILABLE (data.reason relayer_low_balance, relayer_busy, relayer_stalled, gas_price_above_cap, relayer_timeout or relayer_unreachable; Retry-After when busy or timed out; relayer_timeout and relayer_unreachable add data.tradeHash: read the status of that trade before quoting again), RPC_UNAVAILABLE. | [Error](#schema-error) |

```sh
curl -s -X POST "https://api.qiguard.com/gasless/submit" \
  -H "qg-api-key: $QG_API_KEY" -H "qg-version: v1" \
  -H "content-type: application/json" --data @body.json
```

`body.json` is a [GaslessSubmitRequest](#schema-gaslesssubmitrequest): `chainId`, and the `trade` object of your gasless quote unchanged with the signature split into `v`, `r`, `s`.

## GET /gasless/status/{tradeHash}

Status of a submitted gasless trade.

Only the app that submitted the trade can read it. `confirmed` means 5 confirmations on BSC and 3 on Base.

- Key: API key (`qg-api-key`) and `qg-version: v1`
- Endpoint id: `gasless.status` (the name used in the dashboard usage tables)
- Operation id: `gasless_getStatus`

### Parameters of GET /gasless/status/{tradeHash}

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `qg-version` | header | yes | string, one of `v1` | API version. Missing gives `400 API_VERSION_MISSING`; another value gives `400 INPUT_INVALID`. |
| `tradeHash` | path | yes | [Bytes32](#schema-bytes32) |  |
| `chainId` | query | yes | integer, one of `56`, `8453` | Gasless chains are BSC (56) and Base (8453). Other values give `400 CHAIN_NOT_SUPPORTED`. |

### Responses of GET /gasless/status/{tradeHash}

| Status | Meaning | Body |
|---|---|---|
| 200 | Current status. | [GaslessStatus](#schema-gaslessstatus) |
| 400 | INPUT_INVALID, HTTPS_REQUIRED, API_VERSION_MISSING, CHAIN_NOT_SUPPORTED, TOKEN_NOT_SUPPORTED, TOKEN_PAIR_NOT_SUPPORTED, RECIPIENT_NOT_SUPPORTED, SELL_AMOUNT_TOO_SMALL, INSUFFICIENT_BALANCE (gasless quote only), SWAP_VALIDATION_FAILED, UNABLE_TO_CALCULATE_GAS_FEE, SMART_WALLET_NOT_SUPPORTED, INTEGRATOR_FEE_NOT_SUPPORTED, EXACT_OUT_NOT_SUPPORTED, IDEMPOTENCY_KEY_REUSED; on submit also INSUFFICIENT_BALANCE_OR_ALLOWANCE, INVALID_APPROVAL, INVALID_SIGNATURE, INVALID_SIGNER, META_TRANSACTION_EXPIRY_TOO_SOON, META_TRANSACTION_INVALID, PENDING_TRADES_ALREADY_EXIST, TRADE_ALREADY_SUBMITTED. | [Error](#schema-error) |
| 401 | API_KEY_MISSING (message "No API key found in request") or API_KEY_INVALID (unknown, malformed or revoked key). | [Error](#schema-error) |
| 403 | APP_NOT_APPROVED (data.status pending or suspended), PRODUCT_NOT_ENABLED (data.reason product_not_enabled or chain_not_enabled), ORIGIN_NOT_ALLOWED, TAKER_NOT_AUTHORIZED_FOR_TRADE (data.reason denied or gasless_blocked). | [Error](#schema-error) |
| 404 | META_TRANSACTION_STATUS_NOT_FOUND, or NOT_FOUND for an unknown path. | [Error](#schema-error) |
| 429 | RATE_LIMITED (Retry-After 10), QUOTA_EXCEEDED (daily request cap or gasless submits per day; Retry-After = seconds to 00:00 UTC), GAS_BUDGET_EXCEEDED (sponsored-gas budget of the app, the chain or the free tier). | [Error](#schema-error) |
| 500 | INTERNAL_SERVER_ERROR or UNCATEGORIZED. | [Error](#schema-error) |

```sh
curl -s "https://api.qiguard.com/gasless/status/0xa80ae1ca92ebcfd14acb76387a103bd132a66ae86d4292e38550b1d2529e9b10?chainId=8453" \
  -H "qg-api-key: $QG_API_KEY" -H "qg-version: v1"
```

The example `tradeHash` is the test-vector digest; use the `tradeHash` of your own submit.

## GET /swap/chains

Chains supported by the Swap endpoints.

- Key: none
- Endpoint id: `meta.swap_chains` (the name used in the dashboard usage tables)
- Operation id: `swap_getChains`

### Responses of GET /swap/chains

| Status | Meaning | Body |
|---|---|---|
| 200 | Supported chains. | [ChainsResponse](#schema-chainsresponse) |
| 500 | INTERNAL_SERVER_ERROR or UNCATEGORIZED. | [Error](#schema-error) |

```sh
curl -s "https://api.qiguard.com/swap/chains"
```

Example answer:

```json
{
  "chains": [
    {
      "chainId": 56,
      "chainName": "BSC"
    },
    {
      "chainId": 1,
      "chainName": "Ethereum"
    },
    {
      "chainId": 8453,
      "chainName": "Base"
    },
    {
      "chainId": 137,
      "chainName": "Polygon"
    }
  ],
  "zid": "0x0b7a51f2e9c4d3a8812e6f40"
}
```

## GET /gasless/chains

Chains supported by the Gasless endpoints.

`enabled: false` means price and quote work but submit returns `503 GASLESS_NOT_ENABLED`.

- Key: none
- Endpoint id: `meta.gasless_chains` (the name used in the dashboard usage tables)
- Operation id: `gasless_getChains`

### Responses of GET /gasless/chains

| Status | Meaning | Body |
|---|---|---|
| 200 | Gasless chains. | [GaslessChainsResponse](#schema-gaslesschainsresponse) |
| 500 | INTERNAL_SERVER_ERROR or UNCATEGORIZED. | [Error](#schema-error) |

```sh
curl -s "https://api.qiguard.com/gasless/chains"
```

Example answer:

```json
{
  "chains": [
    {
      "chainId": 56,
      "chainName": "BSC",
      "enabled": false
    },
    {
      "chainId": 8453,
      "chainName": "Base",
      "enabled": false
    }
  ],
  "zid": "0x0b7a51f2e9c4d3a8812e6f40"
}
```

## GET /sources

Liquidity sources of a chain (names usable in excludedSources).

- Key: none
- Endpoint id: `meta.sources` (the name used in the dashboard usage tables)
- Operation id: `sources_getSources`

### Parameters of GET /sources

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `chainId` | query | yes | integer, one of `1`, `56`, `137`, `8453` |  |

### Responses of GET /sources

| Status | Meaning | Body |
|---|---|---|
| 200 | Source names. | [SourcesResponse](#schema-sourcesresponse) |
| 400 | INPUT_INVALID, HTTPS_REQUIRED, API_VERSION_MISSING, CHAIN_NOT_SUPPORTED, TOKEN_NOT_SUPPORTED, TOKEN_PAIR_NOT_SUPPORTED, RECIPIENT_NOT_SUPPORTED, SELL_AMOUNT_TOO_SMALL, INSUFFICIENT_BALANCE (gasless quote only), SWAP_VALIDATION_FAILED, UNABLE_TO_CALCULATE_GAS_FEE, SMART_WALLET_NOT_SUPPORTED, INTEGRATOR_FEE_NOT_SUPPORTED, EXACT_OUT_NOT_SUPPORTED, IDEMPOTENCY_KEY_REUSED; on submit also INSUFFICIENT_BALANCE_OR_ALLOWANCE, INVALID_APPROVAL, INVALID_SIGNATURE, INVALID_SIGNER, META_TRANSACTION_EXPIRY_TOO_SOON, META_TRANSACTION_INVALID, PENDING_TRADES_ALREADY_EXIST, TRADE_ALREADY_SUBMITTED. | [Error](#schema-error) |
| 500 | INTERNAL_SERVER_ERROR or UNCATEGORIZED. | [Error](#schema-error) |

```sh
curl -s "https://api.qiguard.com/sources?chainId=56"
```

Example answer:

```json
{
  "sources": [
    "PancakeSwap_V2",
    "PancakeSwap_V3"
  ],
  "zid": "0x0b7a51f2e9c4d3a8812e6f40"
}
```

## GET /tokens

Tokens and anchors supported on a chain.

- Key: none
- Endpoint id: `meta.tokens` (the name used in the dashboard usage tables)
- Operation id: `tokens_getTokens`

### Parameters of GET /tokens

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `chainId` | query | yes | integer, one of `1`, `56`, `137`, `8453` |  |

### Responses of GET /tokens

| Status | Meaning | Body |
|---|---|---|
| 200 | Token list. | [TokensResponse](#schema-tokensresponse) |
| 400 | INPUT_INVALID, HTTPS_REQUIRED, API_VERSION_MISSING, CHAIN_NOT_SUPPORTED, TOKEN_NOT_SUPPORTED, TOKEN_PAIR_NOT_SUPPORTED, RECIPIENT_NOT_SUPPORTED, SELL_AMOUNT_TOO_SMALL, INSUFFICIENT_BALANCE (gasless quote only), SWAP_VALIDATION_FAILED, UNABLE_TO_CALCULATE_GAS_FEE, SMART_WALLET_NOT_SUPPORTED, INTEGRATOR_FEE_NOT_SUPPORTED, EXACT_OUT_NOT_SUPPORTED, IDEMPOTENCY_KEY_REUSED; on submit also INSUFFICIENT_BALANCE_OR_ALLOWANCE, INVALID_APPROVAL, INVALID_SIGNATURE, INVALID_SIGNER, META_TRANSACTION_EXPIRY_TOO_SOON, META_TRANSACTION_INVALID, PENDING_TRADES_ALREADY_EXIST, TRADE_ALREADY_SUBMITTED. | [Error](#schema-error) |
| 500 | INTERNAL_SERVER_ERROR or UNCATEGORIZED. | [Error](#schema-error) |

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

## GET /status

Live state of every chain (contract pause flag, RPC, swap and gasless availability).

- Key: none
- Endpoint id: `meta.status` (the name used in the dashboard usage tables)
- Operation id: `status_getStatus`

### Responses of GET /status

| Status | Meaning | Body |
|---|---|---|
| 200 | Status, cached for 15 seconds. | [StatusResponse](#schema-statusresponse) |
| 500 | INTERNAL_SERVER_ERROR or UNCATEGORIZED. | [Error](#schema-error) |

```sh
curl -s "https://api.qiguard.com/status"
```

## Response headers

| Header | Description |
|---|---|
| `qg-zid` | Request id, the same value as the body `zid`. |
| `RateLimit-Policy` | The app burst limit, for example `"burst";q=50;w=10` (5 requests per second counted over 10 seconds). A `"daily"` part is added only when the app has a daily cap. |
| `Retry-After` | Seconds to wait before retrying. |
| `qg-quota-remaining` | Approximate requests left today; sent only when the app has a daily cap. |
| `qg-quota-reset` | Seconds until 00:00 UTC; sent only when the app has a daily cap. |

## Error responses

Every error has the body [Error](#schema-error). The full list of names, with the extra `data` fields, is on the [errors page](errors.md).

| Response | Names |
|---|---|
| BadRequest | INPUT_INVALID, HTTPS_REQUIRED, API_VERSION_MISSING, CHAIN_NOT_SUPPORTED, TOKEN_NOT_SUPPORTED, TOKEN_PAIR_NOT_SUPPORTED, RECIPIENT_NOT_SUPPORTED, SELL_AMOUNT_TOO_SMALL, INSUFFICIENT_BALANCE (gasless quote only), SWAP_VALIDATION_FAILED, UNABLE_TO_CALCULATE_GAS_FEE, SMART_WALLET_NOT_SUPPORTED, INTEGRATOR_FEE_NOT_SUPPORTED, EXACT_OUT_NOT_SUPPORTED, IDEMPOTENCY_KEY_REUSED; on submit also INSUFFICIENT_BALANCE_OR_ALLOWANCE, INVALID_APPROVAL, INVALID_SIGNATURE, INVALID_SIGNER, META_TRANSACTION_EXPIRY_TOO_SOON, META_TRANSACTION_INVALID, PENDING_TRADES_ALREADY_EXIST, TRADE_ALREADY_SUBMITTED. |
| Unauthorized | API_KEY_MISSING (message "No API key found in request") or API_KEY_INVALID (unknown, malformed or revoked key). |
| Forbidden | APP_NOT_APPROVED (data.status pending or suspended), PRODUCT_NOT_ENABLED (data.reason product_not_enabled or chain_not_enabled), ORIGIN_NOT_ALLOWED, TAKER_NOT_AUTHORIZED_FOR_TRADE (data.reason denied or gasless_blocked). |
| NotFound | META_TRANSACTION_STATUS_NOT_FOUND, or NOT_FOUND for an unknown path. |
| PayloadTooLarge | PAYLOAD_TOO_LARGE (body above 256 KB). |
| TooManyRequests | RATE_LIMITED (Retry-After 10), QUOTA_EXCEEDED (daily request cap or gasless submits per day; Retry-After = seconds to 00:00 UTC), GAS_BUDGET_EXCEEDED (sponsored-gas budget of the app, the chain or the free tier). |
| InternalError | INTERNAL_SERVER_ERROR or UNCATEGORIZED. |
| Unavailable | SETTLEMENT_PAUSED (contract paused), SWAP_NOT_ENABLED (swap switched off for the chain), GASLESS_NOT_ENABLED (data.reason gasless_not_enabled: relayer not set up or funded yet, or switched off), RELAYER_UNAVAILABLE (data.reason relayer_low_balance, relayer_busy, relayer_stalled, gas_price_above_cap, relayer_timeout or relayer_unreachable; Retry-After when busy or timed out; relayer_timeout and relayer_unreachable add data.tradeHash: read the status of that trade before quoting again), RPC_UNAVAILABLE. |

## Schemas

### Schema Address

Type: string, pattern `^0x[0-9a-fA-F]{40}$`.

### Schema Uint

Unsigned integer as a decimal string.

Type: string, pattern `^[0-9]{1,78}$`.

### Schema Hex

Type: string, pattern `^0x([0-9a-fA-F]{2})*$`.

### Schema Bytes32

Type: string, pattern `^0x[0-9a-fA-F]{64}$`.

### Schema Zid

Request id, 0x + 12 random bytes.

Type: string, pattern `^0x[0-9a-f]{24}$`.

### Schema Error

| Field | Type | Required | Description |
|---|---|---|---|
| `name` | string | yes | Error code, see the error table in the docs. |
| `message` | string | yes |  |
| `data` | object | yes |  |
| `data.zid` | [Zid](#schema-zid) | yes |  |
| `data.details` | array of object | no |  |
| `data.details[].field` | string | yes |  |
| `data.details[].reason` | string | yes |  |
| `data.reason` | string | no | Short machine-readable sub-reason, for example gasless_not_enabled, gasless_blocked, price_moved. |

```json
{
  "name": "INPUT_INVALID",
  "message": "sellAmount must be a positive integer string",
  "data": {
    "zid": "0x7d1e0c55a9b2f4e83c61d0aa",
    "details": [
      {
        "field": "sellAmount",
        "reason": "not an integer"
      }
    ]
  }
}
```

### Schema Warning

| Field | Type | Required | Description |
|---|---|---|---|
| `code` | string, one of `trade_surplus_ignored`, `tx_origin_ignored`, `wrap_unwrap_mode_ignored`, `slippage_ppm_rounded`, `secret_key_origin_header`, `gasless_not_enabled` | yes |  |
| `message` | string | yes |  |

### Schema NoLiquidity

| Field | Type | Required | Description |
|---|---|---|---|
| `liquidityAvailable` | boolean, always `false` | yes |  |
| `zid` | [Zid](#schema-zid) | yes |  |

### Schema QiguardFee

The Qiguard fee of the app's plan (Free 25 bps, paid plans 0), taken on chain from the gross output in the buy token. On a chain without a router it is the settlement fee (USDT-input trades pay it from the sell amount in USDT).

| Field | Type | Required | Description |
|---|---|---|---|
| `amount` | [Uint](#schema-uint) | yes |  |
| `token` | [Address](#schema-address) | yes |  |
| `type` | string, always `"volume"` | yes |  |
| `bps` | integer, 0 to 100 | yes |  |
| `takenFrom` | string, one of `sell`, `buy` | yes |  |

### Schema IntegratorFee

One integrator fee (swapFeeRecipient / swapFeeBps), paid on chain to the recipient in the same transaction.

| Field | Type | Required | Description |
|---|---|---|---|
| `amount` | [Uint](#schema-uint) | yes |  |
| `token` | [Address](#schema-address) | yes |  |
| `type` | string, always `"volume"` | yes |  |
| `recipient` | [Address](#schema-address) | yes |  |
| `bps` | integer, 1 to 300 | yes |  |

### Schema GasFee

Gasless only. In v1 the gas is sponsored, so amount is always "0".

| Field | Type | Required | Description |
|---|---|---|---|
| `amount` | [Uint](#schema-uint) | yes |  |
| `token` | [Address](#schema-address) | yes |  |
| `type` | string, always `"gas"` | yes |  |
| `sponsored` | boolean | yes |  |
| `estimatedCostUsd` | string | no | Estimated gas cost in USD, decimal string. |

### Schema Fees

| Field | Type | Required | Description |
|---|---|---|---|
| `integratorFee` | [IntegratorFee](#schema-integratorfee) or null | yes | The first integrator fee, or null. |
| `integratorFees` | array of [IntegratorFee](#schema-integratorfee) | yes |  |
| `qiguardFee` | [QiguardFee](#schema-qiguardfee) | yes |  |
| `gasFee` | [GasFee](#schema-gasfee) or null | yes |  |

### Schema Issues

| Field | Type | Required | Description |
|---|---|---|---|
| `allowance` | object or null | yes |  |
| `allowance.actual` | [Uint](#schema-uint) | yes |  |
| `allowance.spender` | [Address](#schema-address) | yes |  |
| `allowance.resetRequired` | boolean | no | True for Ethereum USDT with a non-zero allowance below sellAmount; approve 0 first. |
| `balance` | object or null | yes |  |
| `balance.token` | [Address](#schema-address) | yes |  |
| `balance.actual` | [Uint](#schema-uint) | yes |  |
| `balance.expected` | [Uint](#schema-uint) | yes |  |
| `simulationIncomplete` | boolean | yes |  |
| `invalidSourcesPassed` | array of string | yes |  |

### Schema RouteFill

| Field | Type | Required | Description |
|---|---|---|---|
| `from` | [Address](#schema-address) | yes |  |
| `to` | [Address](#schema-address) | yes |  |
| `source` | string | yes |  |
| `proportionBps` | string, always `"10000"` | yes |  |
| `feeTier` | integer | no | V3 pool fee in hundredths of a bip; absent on V2 legs. |

### Schema Route

One fill per hop. Phase 1 routes use one source for the whole trade, at most 2 hops.

| Field | Type | Required | Description |
|---|---|---|---|
| `fills` | array of [RouteFill](#schema-routefill) | yes |  |
| `tokens` | array of object | yes |  |
| `tokens[].address` | [Address](#schema-address) | yes |  |
| `tokens[].symbol` | string | yes |  |

### Schema TaxBps

Not measured in v1 (null). Taxed tokens fail simulation and return TOKEN_NOT_SUPPORTED.

| Field | Type | Required | Description |
|---|---|---|---|
| `buyTaxBps` | string or null | yes |  |
| `sellTaxBps` | string or null | yes |  |
| `transferTaxBps` | string or null | yes |  |

### Schema TokenMetadata

| Field | Type | Required | Description |
|---|---|---|---|
| `buyToken` | [TaxBps](#schema-taxbps) | yes |  |
| `sellToken` | [TaxBps](#schema-taxbps) | yes |  |

### Schema Transaction

| Field | Type | Required | Description |
|---|---|---|---|
| `to` | [Address](#schema-address) | yes |  |
| `data` | [Hex](#schema-hex) | yes |  |
| `gas` | [Uint](#schema-uint) | yes |  |
| `gasPrice` | [Uint](#schema-uint) | yes |  |
| `value` | [Uint](#schema-uint) | yes |  |

### Schema Protection

| Field | Type | Required | Description |
|---|---|---|---|
| `settlementPaused` | boolean | yes | Live paused() of the settlement contract (cached 15 s). While true, price and quote return 503 SETTLEMENT_PAUSED. |
| `simulation` | string, one of `passed`, `not_run`, `skipped_allowance`, `skipped_balance`, `at_submit` | yes | Swap quote: eth_call of the exact transaction from the taker (passed), or skipped because the allowance or balance is short. Swap price: not_run. Gasless price and quote: at_submit (the relayer simulates before sending). |
| `quoteIntegrity` | object | yes |  |
| `quoteIntegrity.rpcAgreement` | integer | yes | Number of independent RPC operators that agreed (1 on price, 2 on quote). |
| `quoteIntegrity.maxDeviationBps` | integer or null | no |  |
| `quoteIntegrity.block` | integer | yes | Block the quote was read at. |
| `minBuyAmountEnforcedOnchain` | boolean, always `true` | yes |  |
| `priceBand` | object | yes |  |
| `priceBand.onchainEnforced` | boolean | yes | priceBandEnabled() of the contract. |
| `priceBand.priceImpactBps` | integer or null | yes | Execution price against a small reference trade on the same route; quote only, null on price. |
| `mev` | object | yes |  |
| `mev.submission` | string, one of `taker_submits`, `private`, `sequencer` | yes |  |
| `mev.channels` | array of string | no |  |
| `routeBoundBySignature` | boolean | no | Gasless only; false in v1, the signed message does not fix the route. |
| `signatureExposure` | array of string | no | Gasless only; who sees the signed message before inclusion. `qiguard` includes the private (keyed) RPC endpoint the relayer uses to simulate the transaction; no public RPC receives it. |

### Schema QiguardCall

| Field | Type | Required | Description |
|---|---|---|---|
| `function` | string, one of `marketSwap`, `marketSwapNativeToToken`, `marketSwapTokenToNative` | yes |  |
| `selector` | string, one of `0xb5019436`, `0x6f1190c5`, `0x1f60a2c7` | yes |  |
| `adapter` | [Address](#schema-address) | yes |  |
| `deadline` | integer | yes |  |
| `tag` | string, pattern `^0x71673031[0-9a-f]{28}$` or null | yes |  |

### Schema SwapPrice

| Field | Type | Required | Description |
|---|---|---|---|
| `liquidityAvailable` | boolean, always `true` | yes |  |
| `blockNumber` | [Uint](#schema-uint) | yes |  |
| `sellToken` | [Address](#schema-address) | yes |  |
| `buyToken` | [Address](#schema-address) | yes |  |
| `sellAmount` | [Uint](#schema-uint) | yes |  |
| `buyAmount` | [Uint](#schema-uint) | yes | Net amount the taker receives. |
| `minBuyAmount` | [Uint](#schema-uint) | yes |  |
| `allowanceTarget` | [Address](#schema-address) or null | yes | The settlement contract; null when selling the native coin. |
| `fees` | [Fees](#schema-fees) | yes |  |
| `issues` | [Issues](#schema-issues) | yes |  |
| `warnings` | array of [Warning](#schema-warning) | yes |  |
| `route` | [Route](#schema-route) | yes |  |
| `tokenMetadata` | [TokenMetadata](#schema-tokenmetadata) | yes |  |
| `totalNetworkFee` | [Uint](#schema-uint) | yes | gas x gasPrice, plus the L1 data fee on Base. |
| `gas` | [Uint](#schema-uint) | yes |  |
| `gasPrice` | [Uint](#schema-uint) | yes |  |
| `protection` | [Protection](#schema-protection) | yes |  |
| `mode` | string, always `"exact-in"` | yes |  |
| `zid` | [Zid](#schema-zid) | yes |  |

### Schema SwapQuote

| Field | Type | Required | Description |
|---|---|---|---|
| `liquidityAvailable` | boolean, always `true` | yes |  |
| `blockNumber` | [Uint](#schema-uint) | yes |  |
| `expiresAt` | integer | yes | Unix seconds; the deadline inside transaction.data. |
| `sellToken` | [Address](#schema-address) | yes |  |
| `buyToken` | [Address](#schema-address) | yes |  |
| `sellAmount` | [Uint](#schema-uint) | yes |  |
| `buyAmount` | [Uint](#schema-uint) | yes |  |
| `minBuyAmount` | [Uint](#schema-uint) | yes |  |
| `allowanceTarget` | [Address](#schema-address) or null | yes |  |
| `fees` | [Fees](#schema-fees) | yes |  |
| `issues` | [Issues](#schema-issues) | yes |  |
| `warnings` | array of [Warning](#schema-warning) | yes |  |
| `route` | [Route](#schema-route) | yes |  |
| `tokenMetadata` | [TokenMetadata](#schema-tokenmetadata) | yes |  |
| `totalNetworkFee` | [Uint](#schema-uint) | yes |  |
| `transaction` | [Transaction](#schema-transaction) | yes |  |
| `protection` | [Protection](#schema-protection) | yes |  |
| `qiguard` | [QiguardCall](#schema-qiguardcall) | yes |  |
| `mode` | string, always `"exact-in"` | yes |  |
| `zid` | [Zid](#schema-zid) | yes |  |

```json
{
  "liquidityAvailable": true,
  "blockNumber": "129508144",
  "expiresAt": 1793000120,
  "sellToken": "0x55d398326f99059fF775485246999027B3197955",
  "buyToken": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
  "sellAmount": "100000000000000000000",
  "buyAmount": "158640000000000000",
  "minBuyAmount": "157053600000000000",
  "allowanceTarget": "0x79A76e54f354AC7567f97d979EC1b785c15e37d8",
  "fees": {
    "integratorFee": null,
    "integratorFees": [],
    "qiguardFee": {
      "amount": "500000000000000000",
      "token": "0x55d398326f99059fF775485246999027B3197955",
      "type": "volume",
      "bps": 50,
      "takenFrom": "sell"
    },
    "gasFee": null
  },
  "issues": {
    "allowance": {
      "actual": "0",
      "spender": "0x79A76e54f354AC7567f97d979EC1b785c15e37d8"
    },
    "balance": null,
    "simulationIncomplete": true,
    "invalidSourcesPassed": []
  },
  "warnings": [],
  "route": {
    "fills": [
      {
        "from": "0x55d398326f99059fF775485246999027B3197955",
        "to": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
        "source": "PancakeSwap_V3",
        "proportionBps": "10000",
        "feeTier": 100
      }
    ],
    "tokens": [
      {
        "address": "0x55d398326f99059fF775485246999027B3197955",
        "symbol": "USDT"
      },
      {
        "address": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
        "symbol": "WBNB"
      }
    ]
  },
  "tokenMetadata": {
    "buyToken": {
      "buyTaxBps": null,
      "sellTaxBps": null,
      "transferTaxBps": null
    },
    "sellToken": {
      "buyTaxBps": null,
      "sellTaxBps": null,
      "transferTaxBps": null
    }
  },
  "totalNetworkFee": "26000000000000",
  "transaction": {
    "to": "0x79A76e54f354AC7567f97d979EC1b785c15e37d8",
    "data": "0x1f60a2c7...71673031a4c2e09b5d7f1e335f1c9a7e2b44",
    "gas": "260000",
    "gasPrice": "100000000",
    "value": "0"
  },
  "protection": {
    "settlementPaused": false,
    "simulation": "skipped_allowance",
    "quoteIntegrity": {
      "rpcAgreement": 2,
      "maxDeviationBps": 4,
      "block": 129508144
    },
    "minBuyAmountEnforcedOnchain": true,
    "priceBand": {
      "onchainEnforced": false,
      "priceImpactBps": 3
    },
    "mev": {
      "submission": "taker_submits"
    }
  },
  "qiguard": {
    "function": "marketSwapTokenToNative",
    "selector": "0x1f60a2c7",
    "adapter": "0xb8dfc084c3912B71662044092722fdDA40b15Ab3",
    "deadline": 1793000120,
    "tag": "0x71673031a4c2e09b5d7f1e335f1c9a7e2b44"
  },
  "mode": "exact-in",
  "zid": "0x5f1c9a7e2b44d0c3a1e8f6b2"
}
```

### Schema PermitWitnessMessage

| Field | Type | Required | Description |
|---|---|---|---|
| `permitted` | object | yes |  |
| `permitted.token` | [Address](#schema-address) | yes |  |
| `permitted.amount` | [Uint](#schema-uint) | yes |  |
| `spender` | [Address](#schema-address) | yes | The settlement contract of the chain. |
| `nonce` | [Uint](#schema-uint) | yes | Random unordered Permit2 nonce. |
| `deadline` | [Uint](#schema-uint) | yes |  |
| `witness` | object | yes |  |
| `witness.tokenOut` | [Address](#schema-address) | yes |  |
| `witness.minAmountOut` | [Uint](#schema-uint) | yes |  |
| `witness.recipient` | [Address](#schema-address) | yes | Must be the taker (the signer). |
| `witness.adapter` | [Address](#schema-address) | yes |  |
| `witness.deadline` | [Uint](#schema-uint) | yes | Equal to the outer deadline. |

### Schema PermitWitnessTypedData

Must be sent back exactly as returned by /gasless/quote: any change to types, primaryType or domain gives META_TRANSACTION_INVALID. The digest of this object is the tradeHash.

| Field | Type | Required | Description |
|---|---|---|---|
| `types` | object | yes |  |
| `types.EIP712Domain` | [Eip712Fields](#schema-eip712fields) | yes |  |
| `types.PermitWitnessTransferFrom` | [Eip712Fields](#schema-eip712fields) | yes |  |
| `types.TokenPermissions` | [Eip712Fields](#schema-eip712fields) | yes |  |
| `types.OrderWitness` | [Eip712Fields](#schema-eip712fields) | yes |  |
| `primaryType` | string, always `"PermitWitnessTransferFrom"` | yes |  |
| `domain` | object | yes |  |
| `domain.name` | string, always `"Permit2"` | yes |  |
| `domain.chainId` | integer, one of `56`, `8453` | yes |  |
| `domain.verifyingContract` | string, always `"0x000000000022D473030F116dDEE9F6B43aC78BA3"` | yes |  |
| `message` | [PermitWitnessMessage](#schema-permitwitnessmessage) | yes |  |

```json
{
  "types": {
    "EIP712Domain": [
      {
        "name": "name",
        "type": "string"
      },
      {
        "name": "chainId",
        "type": "uint256"
      },
      {
        "name": "verifyingContract",
        "type": "address"
      }
    ],
    "PermitWitnessTransferFrom": [
      {
        "name": "permitted",
        "type": "TokenPermissions"
      },
      {
        "name": "spender",
        "type": "address"
      },
      {
        "name": "nonce",
        "type": "uint256"
      },
      {
        "name": "deadline",
        "type": "uint256"
      },
      {
        "name": "witness",
        "type": "OrderWitness"
      }
    ],
    "TokenPermissions": [
      {
        "name": "token",
        "type": "address"
      },
      {
        "name": "amount",
        "type": "uint256"
      }
    ],
    "OrderWitness": [
      {
        "name": "tokenOut",
        "type": "address"
      },
      {
        "name": "minAmountOut",
        "type": "uint256"
      },
      {
        "name": "recipient",
        "type": "address"
      },
      {
        "name": "adapter",
        "type": "address"
      },
      {
        "name": "deadline",
        "type": "uint256"
      }
    ]
  },
  "primaryType": "PermitWitnessTransferFrom",
  "domain": {
    "name": "Permit2",
    "chainId": 8453,
    "verifyingContract": "0x000000000022D473030F116dDEE9F6B43aC78BA3"
  },
  "message": {
    "permitted": {
      "token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "amount": "25000000"
    },
    "spender": "0x67433187Db1e57f66E88880b6Be833f6759362b1",
    "nonce": "123456789012345678901234567890",
    "deadline": "1793000120",
    "witness": {
      "tokenOut": "0x4200000000000000000000000000000000000006",
      "minAmountOut": "5981940000000000",
      "recipient": "0x1111111111111111111111111111111111111111",
      "adapter": "0xB47011d787B432ccF7A53284a74432a0De4397a3",
      "deadline": "1793000120"
    }
  }
}
```

### Schema Eip712Fields

Type: array of object, items with `name`, `type`.

### Schema GaslessTrade

| Field | Type | Required | Description |
|---|---|---|---|
| `type` | string, always `"qiguard_permit2_witness"` | yes |  |
| `hash` | [Bytes32](#schema-bytes32) | yes | EIP-712 digest of eip712; equals the tradeHash returned by submit. |
| `eip712` | [PermitWitnessTypedData](#schema-permitwitnesstypeddata) | yes |  |

### Schema GaslessPrice

| Field | Type | Required | Description |
|---|---|---|---|
| `liquidityAvailable` | boolean, always `true` | yes |  |
| `blockNumber` | [Uint](#schema-uint) | yes |  |
| `sellToken` | [Address](#schema-address) | yes |  |
| `buyToken` | [Address](#schema-address) | yes |  |
| `sellAmount` | [Uint](#schema-uint) | yes |  |
| `buyAmount` | [Uint](#schema-uint) | yes |  |
| `minBuyAmount` | [Uint](#schema-uint) | yes |  |
| `target` | [Address](#schema-address) | yes | The settlement contract (the Permit2 spender). |
| `fees` | [Fees](#schema-fees) | yes |  |
| `issues` | [Issues](#schema-issues) | yes |  |
| `warnings` | array of [Warning](#schema-warning) | yes |  |
| `route` | [Route](#schema-route) | yes |  |
| `tokenMetadata` | [TokenMetadata](#schema-tokenmetadata) | yes |  |
| `protection` | [Protection](#schema-protection) | yes |  |
| `zid` | [Zid](#schema-zid) | yes |  |

### Schema GaslessQuote

| Field | Type | Required | Description |
|---|---|---|---|
| `liquidityAvailable` | boolean, always `true` | yes |  |
| `blockNumber` | [Uint](#schema-uint) | yes |  |
| `expiresAt` | integer | yes | The signed deadline (unix seconds). |
| `sellToken` | [Address](#schema-address) | yes |  |
| `buyToken` | [Address](#schema-address) | yes |  |
| `sellAmount` | [Uint](#schema-uint) | yes |  |
| `buyAmount` | [Uint](#schema-uint) | yes |  |
| `minBuyAmount` | [Uint](#schema-uint) | yes |  |
| `target` | [Address](#schema-address) | yes |  |
| `approval` | null | yes | Always null in v1. |
| `trade` | [GaslessTrade](#schema-gaslesstrade) | yes |  |
| `fees` | [Fees](#schema-fees) | yes |  |
| `issues` | [Issues](#schema-issues) | yes |  |
| `warnings` | array of [Warning](#schema-warning) | yes |  |
| `route` | [Route](#schema-route) | yes |  |
| `tokenMetadata` | [TokenMetadata](#schema-tokenmetadata) | yes |  |
| `protection` | [Protection](#schema-protection) | yes |  |
| `zid` | [Zid](#schema-zid) | yes |  |

### Schema Signature

| Field | Type | Required | Description |
|---|---|---|---|
| `signatureType` | integer, always `2` | yes | 2 = EIP-712 ECDSA signature of an EOA. |
| `v` | integer, one of `27`, `28` | yes |  |
| `r` | [Bytes32](#schema-bytes32) | yes |  |
| `s` | [Bytes32](#schema-bytes32) | yes |  |

### Schema GaslessSubmitRequest

| Field | Type | Required | Description |
|---|---|---|---|
| `chainId` | integer, one of `56`, `8453` | yes |  |
| `trade` | object | yes |  |
| `trade.type` | string, always `"qiguard_permit2_witness"` | yes |  |
| `trade.eip712` | [PermitWitnessTypedData](#schema-permitwitnesstypeddata) | yes |  |
| `trade.signature` | [Signature](#schema-signature) | yes |  |
| `approval` | null | no | Must be absent or null in v1; anything else gives INVALID_APPROVAL. |

### Schema GaslessSubmitResponse

| Field | Type | Required | Description |
|---|---|---|---|
| `tradeHash` | [Bytes32](#schema-bytes32) | yes |  |
| `type` | string, always `"qiguard_permit2_witness"` | yes |  |
| `zid` | [Zid](#schema-zid) | yes |  |

### Schema GaslessStatus

| Field | Type | Required | Description |
|---|---|---|---|
| `status` | string, one of `pending`, `submitted`, `succeeded`, `confirmed`, `failed` | yes |  |
| `transactions` | array of object | yes | Every hash broadcast for this trade (rebroadcasts and replacements included). |
| `transactions[].hash` | [Bytes32](#schema-bytes32) | yes |  |
| `transactions[].timestamp` | integer | yes |  |
| `approvalTransactions` | array of any, always empty | yes |  |
| `reason` | string, one of `transaction_simulation_failed`, `order_expired`, `transaction_reverted`, `insufficient_allowance`, `insufficient_balance`, `internal_error` | no | Present when status is failed. |
| `detail` | string | no | Optional extra detail, for example slippage or permit_consumed_by_other_tx. |
| `zid` | [Zid](#schema-zid) | yes |  |

### Schema ChainsResponse

| Field | Type | Required | Description |
|---|---|---|---|
| `chains` | array of object | yes |  |
| `chains[].chainId` | integer | yes |  |
| `chains[].chainName` | string | yes |  |
| `zid` | [Zid](#schema-zid) | yes |  |

### Schema GaslessChainsResponse

| Field | Type | Required | Description |
|---|---|---|---|
| `chains` | array of object | yes |  |
| `chains[].chainId` | integer | yes |  |
| `chains[].chainName` | string | yes |  |
| `chains[].enabled` | boolean | yes | False until the relayer is funded and gasless is switched on for the chain. |
| `zid` | [Zid](#schema-zid) | yes |  |

### Schema SourcesResponse

| Field | Type | Required | Description |
|---|---|---|---|
| `sources` | array of string | yes |  |
| `zid` | [Zid](#schema-zid) | yes |  |

### Schema TokensResponse

| Field | Type | Required | Description |
|---|---|---|---|
| `tokens` | array of object | yes |  |
| `tokens[].address` | [Address](#schema-address) | yes |  |
| `tokens[].symbol` | string | yes |  |
| `tokens[].decimals` | integer | yes |  |
| `tokens[].anchor` | boolean | yes | USDT, USDC, the native coin or the wrapped native token. Every pair needs an anchor on one side. |
| `tokens[].gasless` | boolean | yes | Usable on the gasless endpoints of this chain (ERC-20 on a gasless chain). |
| `zid` | [Zid](#schema-zid) | yes |  |

### Schema StatusResponse

| Field | Type | Required | Description |
|---|---|---|---|
| `version` | string | yes |  |
| `time` | string, format date-time | yes |  |
| `chains` | array of object | yes |  |
| `chains[].chainId` | integer | yes |  |
| `chains[].chainName` | string | yes |  |
| `chains[].settlement` | [Address](#schema-address) | yes |  |
| `chains[].paused` | boolean | yes |  |
| `chains[].priceBandEnforced` | boolean | yes |  |
| `chains[].feeRecipient` | [Address](#schema-address) | yes |  |
| `chains[].headBlock` | integer | yes |  |
| `chains[].rpc` | string, one of `ok`, `degraded`, `down` | yes |  |
| `chains[].swap` | string, one of `operational`, `paused`, `switched_off`, `degraded` | yes |  |
| `chains[].gasless` | object | yes |  |
| `chains[].gasless.state` | string, one of `not_listed`, `not_enabled`, `operational`, `switched_off`, `relayer_low`, `relayer_busy`, `relayer_stalled`, `paused`, `degraded` | yes |  |
| `chains[].gasless.relayer` | string, one of `ok`, `low`, `empty`, `unknown` | no |  |
| `chains[].gasless.queued` | integer | no |  |
| `zid` | [Zid](#schema-zid) | yes |  |
