> ## Documentation Index
> Fetch the complete documentation index at: https://developers.jup.ag/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Gasless Swaps

> Let users swap without holding SOL for transaction fees

Gasless swaps let users trade without holding SOL for transaction fees. On `/order`, the `gasless: true` response field can be set by three independent paths:

1. **Automatic Jupiter sponsorship:** Jupiter covers gas and token account rent when the taker has low SOL.
2. **JupiterZ market maker:** an RFQ market maker pays signature and priority fees directly.
3. **Integrator payer:** your wallet covers gas via the `payer` parameter.

To identify which path fired on any quote, compare `signatureFeePayer` to the `taker`:

| `signatureFeePayer` value | Source |
| - | - |
| Equal to `taker` | Not gasless, taker pays |
| `gasTzr94Pmp4Gf8vknQnqxeYxdgwFjbgdJa4msYRpnB` | Automatic Jupiter sponsorship |
| Equal to your `payer` parameter | Integrator-sponsored gas (Metis route) |
| Any other address | JupiterZ market maker (varies per quote) |

When you set `payer` and a JupiterZ market maker wins the quote, `signatureFeePayer` is the market maker and `rentFeePayer` is your `payer` (or the taker when the output is native SOL, since no output token account is created). See [Integrator payer](#integrator-payer).

## Types of gas costs

Solana transactions can incur four types of gas costs:

1. **Base network transaction fee** (signature fee)
2. **Associated token account (ATA) rent** for new token accounts
3. **Priority fee** (or tips for Jito, etc.)
4. **Other account rent** (some DEXes require additional accounts of the taker, e.g. Pump.fun)

## How to opt out of gasless

The most reliable check is `signatureFeePayer == taker` on every `/order` response. Drop any quote where they differ. This catches all three gasless paths and survives future changes to routing.

You can also reduce gasless quotes upstream by passing `excludeRouters=jupiterz`. This blocks the JupiterZ RFQ path, which is the most common source of gasless quotes. It is not a complete opt-out on its own: if the taker has less than 0.01 SOL on a trade of about \$10 or more, automatic Jupiter sponsorship still fires through Metis with `signatureFeePayer = gasTzr94Pmp4Gf8vknQnqxeYxdgwFjbgdJa4msYRpnB`. The `signatureFeePayer` check catches both cases.

## Automatic gasless (`/order`)

Jupiter automatically covers gas costs when the taker lacks SOL.

**When it applies:**

* Taker has less than 0.01 SOL
* Minimum trade size of \~\$10 (dynamic, varies with current priority fee market)
* A JupiterZ market maker is not winning the quote, and integrator `payer` is not set

**What it covers:** all four gas types (signature fee, priority fee, ATA rent, other account rent).

**How it works:**

* Jupiter calculates the required SOL to cover gas and increases the swap fee. The taker receives less output tokens. The top-level `feeBps` field reflects this increased total fee, while `platformFee.feeBps` only reflects the Jupiter platform fee.
* The sponsor wallet `gasTzr94Pmp4Gf8vknQnqxeYxdgwFjbgdJa4msYRpnB` is added as a secondary signer and is returned as the `signatureFeePayer`, `prioritizationFeePayer`, and `rentFeePayer` in the response.

**Limitations:**

* Does not fire when `payer` is set to a wallet other than the taker (integrator payer takes over instead)
* Does not fire when `referralAccount` and `referralFee` are set

## JupiterZ gasless (`/order`)

When a JupiterZ (RFQ) market maker wins the quote on `/order`, the market maker pays network and priority fees directly. Output token account rent is separate: when referral fees are not set, Jupiter's gas wallet (`gasTzr94Pmp4Gf8vknQnqxeYxdgwFjbgdJa4msYRpnB`) can pay the rent to create the taker's output token account. With referral fees, the taker pays output token account rent. With an integrator `payer`, the payer pays it (see [Integrator payer](#integrator-payer)).

**When it applies:**

* Taker trades a pair the market makers are willing to quote

**What it covers:** signature fee and priority fee. Output token account rent can be covered by Jupiter's gas wallet when referral fees are not set.

**How it works:**

* The order transaction includes a secondary signer for the market maker
* Jupiter sets the gas payer to the MM signer and on `/execute`, your partially signed transaction is sent to the MM for them to co-sign and execute
* If the taker's output token account is not yet initialised and referral fees are not set, Jupiter's gas wallet (`gasTzr94Pmp4Gf8vknQnqxeYxdgwFjbgdJa4msYRpnB`) can pay the rent to create it
* The `signatureFeePayer` is the MM's address. MM addresses vary per quote, so do not hardcode against a single address. Use the `signatureFeePayer != taker` check instead.

**Limitations:**

* With `referralAccount` and `referralFee`, JupiterZ can still quote and execute, but the taker must have enough SOL for any required output token account rent, unless you set `payer`, which pays that rent instead

## Integrator payer

Integrators can sponsor gas for their users by passing the `payer` parameter, so the user does not need SOL to swap. This works on both `/order` and `/build`.

> [!NOTE]
>
> `payer` only activates when set to a wallet different from `taker`. Setting `payer=taker` has no effect. The request behaves as if no `payer` was provided.

### On `/order`

Pass `payer` to cover gas-related fees for the taker. Metis and JupiterZ (RFQ) both compete for the quote. Dflow and OKX are not eligible when `payer` is set.

> [!NOTE]
>
> `payer` works without referral parameters, but then you pay gas on every swap with no fee to recover it. Pass `referralAccount` and `referralFee` with `payer` to charge a fee that covers the gas you spend.

```typescript theme={null}
const params = new URLSearchParams({
  inputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC
  outputMint: "So11111111111111111111111111111111111111112",     // SOL
  amount: "1000000",
  taker: userWallet,
  payer: integratorPayerWallet,
});

const response = await fetch(
  `https://api.jup.ag/swap/v2/order?${params}`,
  { headers: { "x-api-key": API_KEY } }
);
```

What the payer pays, and whether it signs, depends on which router wins the quote. Read `router` in the `/order` response:

| | Metis route (`router: "metis"`) | JupiterZ route (`router: "jupiterz"`) |
| - | - | - |
| Signature and priority fees | Payer | Market maker |
| Output token account rent | Payer | Payer |
| Other account rent | Payer | None needed |
| `signatureFeePayer` / `rentFeePayer` | Payer / payer | Market maker / payer (taker for native SOL output) |
| Payer signs | Yes | Yes, unless the output is native SOL |

**How it works on a Metis route:**

* Regardless of how much SOL the taker has, the payer covers all four gas types
* Temporary wSOL ATA rent is covered by the payer and returned in the same transaction
* Other ATAs are covered by the payer but not returned (they hold tokens post-swap)

**How it works on a JupiterZ route:**

* The market maker is the transaction fee payer and pays signature and priority fees
* The payer funds the rent to create the taker's output token account when it does not exist yet, and the receiver's output token account when `receiver` is set. When the account already exists, the payer pays nothing
* The payer is a required signer whenever the output is an SPL token, including when the account already exists and no rent is charged
* When the output is native SOL, the transaction creates no output token account, so the payer is not a signer and pays nothing
* The taker pays no SOL

Before sending to `/execute`, sign with the taker and, only if it is one of the transaction's required signers, with the payer. Match the payer by public key, not by position: the signer order differs between quotes. If you always sign with the payer, signing fails on native SOL output because the payer is not a required signer. `@solana/kit` fails with `Attempted to sign a transaction with an address that is not a signer for it`, and `@solana/web3.js` with `Cannot sign with non signer key <address>`. On a JupiterZ route, the market maker signs during `/execute`.

```typescript title="@solana/kit" theme={null}
import {
  getTransactionDecoder,
  getTransactionEncoder,
  partiallySignTransaction,
} from "@solana/kit";

// order: the /order response
// userSigner, payerSigner: KeyPairSigner from createKeyPairSignerFromBytes
const transaction = getTransactionDecoder().decode(
  Buffer.from(order.transaction, "base64"),
);

// The keys of `signatures` are the transaction's required signers.
// The payer is one of them unless the output is native SOL on a JupiterZ route.
const requiredSigners = Object.keys(transaction.signatures);
const keyPairs = [userSigner, payerSigner]
  .filter((s) => requiredSigners.includes(s.address))
  .map((s) => s.keyPair);

// Partial signing: on a JupiterZ route the market maker signs during /execute
const signedTransaction = await partiallySignTransaction(keyPairs, transaction);
const signedTxBase64 = Buffer.from(
  getTransactionEncoder().encode(signedTransaction),
).toString("base64");
```

```typescript title="@solana/web3.js" theme={null}
import { VersionedTransaction } from "@solana/web3.js";

// order: the /order response
// userKeypair, payerKeypair: Keypair
const transaction = VersionedTransaction.deserialize(
  Buffer.from(order.transaction, "base64"),
);

// The first numRequiredSignatures static keys are the required signers.
// The payer is one of them unless the output is native SOL on a JupiterZ route.
const { header, staticAccountKeys } = transaction.message;
const requiredSigners = staticAccountKeys
  .slice(0, header.numRequiredSignatures)
  .map((key) => key.toBase58());
transaction.sign(
  [userKeypair, payerKeypair].filter((k) =>
    requiredSigners.includes(k.publicKey.toBase58()),
  ),
);
const signedTxBase64 = Buffer.from(transaction.serialize()).toString("base64");
```

Send `signedTxBase64` and the order's `requestId` to `/execute`, as in [Order & Execute](https://developers.jup.ag/docs/swap/order-and-execute.md).

### On `/build`

Pass `payer` to change the fee payer on all returned instructions. The payer address replaces the default `taker` as the fee payer for the transaction.

```typescript theme={null}
const params = new URLSearchParams({
  inputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  outputMint: "So11111111111111111111111111111111111111112",
  amount: "1000000",
  taker: userWallet,
  payer: integratorPayerWallet,
});

const response = await fetch(
  `https://api.jup.ag/swap/v2/build?${params}`,
  { headers: { "x-api-key": API_KEY } }
);
```

The returned instructions will have fee payer accounts set to the `payer` address. You are responsible for building the transaction, collecting both signatures (taker + payer), and sending via your own RPC.

> [!TIP]
>
> 1. When using `payer` on `/build`, do note that your gas payer is not only paying for gas, it is paying for transaction fee, priority fee/tip, token accounts, or any other AMM related accounts that might be required.
>
> 2. The token accounts or AMM related accounts can be closed by the user. If you do not find ways to recoup the fees you spent for the user, it may be gameable where they always close their accounts and you have to fund them again.
>
> Hence, when you are the gas payer, ensure that you account for these and find ways to recoup the cost spent to ensure your gas payer is not drained.

## Related

* [Order & Execute](https://developers.jup.ag/docs/swap/order-and-execute.md) for the default swap flow
* [Build](https://developers.jup.ag/docs/swap/build.md) for full transaction control
* [Routing impact matrix](https://developers.jup.ag/docs/swap/order-and-execute.md#routing-impact-matrix) for how `payer` affects routing
* [Fees](https://developers.jup.ag/docs/swap/order-and-execute.md#fees) for how gasless affects the fee calculation


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.