> For the complete documentation index, see [llms.txt](https://titan-exchange.gitbook.io/titan/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection.md).

# Fee Collection

Collect a fee on every swap by specifying a fee account and basis-point rate in your request.

If you're building a product on top of Titan, you can collect a fee on every swap. Fees are deducted from the swap output (or input) and sent to a token account you control.

## How fees work

The fee is taken from the **output token** by default. If you'd rather take the fee from the input side, set `feeFromInputMint: true`.

Your fee account must be a token account for the correct mint — output mint by default, or input mint when `feeFromInputMint` is true. This account must already exist, or you must add the ATA creation instruction yourself.

When fees are active, every [`SwapRoute`](/titan/developer-doc/swap-api/reference/types.md) in the quote response includes a `platformFee` field with the exact fee amount and rate. Show this to your users before they sign.

These fields are part of [`TransactionParams`](/titan/developer-doc/swap-api/reference/types.md):

* **`feeAccount`** (`Pubkey`) — ATA to receive the fee. Must already exist on-chain, or you must add the ATA creation instruction yourself.
* **`feeBps`** (`u16`) — Fee rate in basis points (1 bps = 0.01%). If not specified, the default fee for your account is used.
* **`feeFromInputMint`** (`bool`) — If `true`, fee is taken from the input mint. Default `false`.

## Collect fees on output token (default)

Create an ATA for the output mint before your first request, then pass `feeAccount` and `feeBps` in your transaction parameters.

{% tabs %}
{% tab title="Titan Direct" %}

```typescript
import WebSocket from 'ws';
import { Encoder, Decoder } from '@msgpack/msgpack';
import bs58 from 'bs58';
import { zstdCompress, zstdDecompress } from 'http-encoding';

const encoder = new Encoder({ useBigInt64: true });
const decoder = new Decoder({ useBigInt64: true });

const url = `${process.env.TITAN_ENDPOINT}?auth=${process.env.TITAN_JWT}`;
const ws = new WebSocket(url, [
  'v1.api.titan.ag+zstd',
  'v1.api.titan.ag',
]);

const SOL  = bs58.decode('So11111111111111111111111111111111111111112');
const USDC = bs58.decode('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
const userPublicKey = bs58.decode('YOUR_WALLET_PUBLIC_KEY');

// Your ATA for the output mint (USDC in this case)
const feeAccount = bs58.decode('YOUR_USDC_FEE_ATA');

let useCompression = false;
let requestId = 0;

ws.on('open', async () => {
  useCompression = ws.protocol !== 'v1.api.titan.ag';

  const id = requestId++;
  const encoded = encoder.encode({
    id,
    data: {
      NewSwapQuoteStream: {
        swap: {
          inputMint: SOL,
          outputMint: USDC,
          amount: 1_000_000_000n, // 1 SOL
          slippageBps: 50,
        },
        transaction: {
          userPublicKey,
          feeAccount,
          feeBps: 100, // 1% fee
        },
      },
    },
  });
  ws.send(useCompression ? await zstdCompress(encoded) : encoded);
});
```

{% endtab %}

{% tab title="Titan Gateway" %}

```typescript
import { decode } from '@msgpack/msgpack';

const SOL  = 'So11111111111111111111111111111111111111112';
const USDC = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';

const params = new URLSearchParams({
  inputMint: SOL,
  outputMint: USDC,
  amount: '1000000000',
  userPublicKey: 'YOUR_WALLET_PUBLIC_KEY',
  slippageBps: '50',
  feeAccount: 'YOUR_USDC_FEE_ATA',    // ATA for the output mint
  feeBps: '100',                        // 1% fee
});

const res = await fetch(
  `${process.env.TITAN_ENDPOINT}/api/v1/quote/swap?${params}`,
  {
    headers: {
      'Authorization': `Bearer ${process.env.TITAN_JWT}`,
      'Accept': 'application/vnd.msgpack',
    },
  }
);

const buffer = await res.arrayBuffer();
const quotes = decode(new Uint8Array(buffer)) as any;
```

{% endtab %}
{% endtabs %}

## Collect fees on input token

Set `feeFromInputMint: true` and make sure your fee account is an ATA for the **input** mint instead of the output mint.

{% tabs %}
{% tab title="Titan Direct" %}

```typescript
import WebSocket from 'ws';
import { Encoder, Decoder } from '@msgpack/msgpack';
import bs58 from 'bs58';
import { zstdCompress, zstdDecompress } from 'http-encoding';

const encoder = new Encoder({ useBigInt64: true });
const decoder = new Decoder({ useBigInt64: true });

const url = `${process.env.TITAN_ENDPOINT}?auth=${process.env.TITAN_JWT}`;
const ws = new WebSocket(url, [
  'v1.api.titan.ag+zstd',
  'v1.api.titan.ag',
]);

const SOL  = bs58.decode('So11111111111111111111111111111111111111112');
const USDC = bs58.decode('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
const userPublicKey = bs58.decode('YOUR_WALLET_PUBLIC_KEY');

// Fee from input — ATA must be for SOL (wrapped SOL), not USDC
const feeAccount = bs58.decode('YOUR_SOL_FEE_ATA');

let useCompression = false;
let requestId = 0;

ws.on('open', async () => {
  useCompression = ws.protocol !== 'v1.api.titan.ag';

  const id = requestId++;
  const encoded = encoder.encode({
    id,
    data: {
      NewSwapQuoteStream: {
        swap: {
          inputMint: SOL,
          outputMint: USDC,
          amount: 1_000_000_000n,
          slippageBps: 50,
        },
        transaction: {
          userPublicKey,
          feeAccount,
          feeBps: 50, // 0.5% fee
          feeFromInputMint: true,
        },
      },
    },
  });
  ws.send(useCompression ? await zstdCompress(encoded) : encoded);
});
```

{% endtab %}

{% tab title="Titan Gateway" %}

```typescript
import { decode } from '@msgpack/msgpack';

const SOL  = 'So11111111111111111111111111111111111111112';
const USDC = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';

const params = new URLSearchParams({
  inputMint: SOL,
  outputMint: USDC,
  amount: '1000000000',
  userPublicKey: 'YOUR_WALLET_PUBLIC_KEY',
  slippageBps: '50',
  feeAccount: 'YOUR_SOL_FEE_ATA',
  feeBps: '50',
  feeFromInputMint: 'true',
});

const res = await fetch(
  `${process.env.TITAN_ENDPOINT}/api/v1/quote/swap?${params}`,
  {
    headers: {
      'Authorization': `Bearer ${process.env.TITAN_JWT}`,
      'Accept': 'application/vnd.msgpack',
    },
  }
);

const buffer = await res.arrayBuffer();
const quotes = decode(new Uint8Array(buffer)) as any;
```

{% endtab %}
{% endtabs %}

## Read the fee from quote response

Every [`SwapRoute`](/titan/developer-doc/swap-api/reference/types.md) that includes a fee has a `platformFee` object. Check it before your user signs — this is what you should display in your UI.

```typescript
// Use metadata.ExpectedWinner for the best slippage-adjusted route
const best = quotes.quotes[quotes.metadata?.ExpectedWinner];

if (best.platformFee) {
  const feeAmount = BigInt(best.platformFee.amount);
  const fee_bps = best.platformFee.fee_bps;

  console.log(`Platform fee: ${feeAmount} tokens (${fee_bps} bps)`);
  // Example: "Platform fee: 1428570 tokens (100 bps)"
}

// Show the fee to your user before they sign
console.log(`Output after fee: ${best.outAmount}`);
```

The [`PlatformFee`](/titan/developer-doc/swap-api/reference/types.md) type:

* **`amount`** (`u64`) — Absolute fee amount in the token's smallest unit.
* **`fee_bps`** (`u8`) — Fee rate in basis points.

## Important notes

{% hint style="warning" %}
Only validated users can specify a `feeAccount`. Contact the Titan team to get your account approved for fee collection.
{% endhint %}

The fee is taken **from** the swap amount, not added on top. If a user swaps 1 SOL and the fee is 1%, the user receives the output for 0.99 SOL worth of input (when `feeFromInputMint` is true) or gets 1% less output (when fees are taken from the output side, the default).

## Related pages

* [Stream & Execute a Swap](/titan/developer-doc/swap-api/guides/stream-and-execute.md) — full guide with transaction building, signing, and error handling
* [Configure Routing](/titan/developer-doc/swap-api/guides/configure-routing.md) — filter venues and providers
* [Types Reference](/titan/developer-doc/swap-api/reference/types.md) — `SwapRoute`, `PlatformFee`, `TransactionParams`, and all type definitions
* [Wire Protocol](/titan/developer-doc/swap-api/reference/wire-protocol.md) — MessagePack encoding and compression
