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

# Collecting your fee

> The four steps that decide whether a swap with your fee on it actually pays you.

A fee set on your key is only paid on swaps RAVN can prove. Two duties decide that, and both are
yours: **pay the `fee` an execution asks for**, and **report the swap to `/status` until it is
final**. Skip either one and the swap still fills for your user, but nothing is owed to you on it.

Run through this list once per integration, and again whenever you add a chain or wallet type.

<Steps>
  <Step title="Read `fee` on every execution">
    Your fee only applies to calls that send your key as `x-api-key`: a keyless quote carries none.
    `/execute` adds a `fee` object only when your key sets a fee and the route has no fee
    mechanism of its own, so RAVN collects yours beside the swap:

    | Execution | Routes |
    | - | - |
    | `DEPOSIT` | Rift, private swaps (`confidential: true`: NEAR Intents, Houdini Swap) |
    | `TRANSACTION` from an EVM chain | Eco Routes, Layerswap, Mayan routes paying no referrer |

    Every other route takes your fee inside the swap itself, so there is nothing extra to pay, but
    step 3 still decides whether you get paid. Never build the fee payment yourself: pay exactly
    what `fee` says.
  </Step>

  <Step title="Pay it the way its chain needs">
    | The swap starts on | `fee` carries | What to do |
    | - | - | - |
    | An EVM chain | `fee.transaction` | Send `fee.transaction` exactly as given: it carries a tag naming this swap. Either as a transaction of its own, sent **only after the swap or deposit has confirmed and its own receipt says success** (a fee paid on a swap that reverts or is refunded stays with RAVN), or inside the same atomic wallet batch as the swap or deposit (EIP-5792 `wallet_sendCalls`, a smart account). One fee-bearing swap per batch. |
    | | an ERC-20 fee (`fee.transaction.value` is `"0"`) | Its own transaction or the same batch: both work. |
    | | a native-coin fee (`value` above `"0"`) | A plain transaction of its own, from a regular wallet. The one exception: beside a NEAR Intents deposit (a private swap) on Ethereum, Base or Polygon, it may ride in the same batch as the deposit. A contract wallet that can't send a plain transaction (a Safe, a 4337 account) can't pay any other native-coin fee. |
    | Bitcoin (Rift, private NEAR Intents) | no `transaction` (`fee.chainId` is `-1`) | Add a second output paying `fee.amount` sats to `fee.address` to the **same** transaction that pays the deposit. One deposit per Bitcoin transaction. A fee under 546 sats isn't charged. |
    | Solana, a private-swap deposit | no `transaction` (`fee.chainId` is `-2`) | Add the transfer to the **same** transaction that pays the deposit. SOL: a System transfer of `fee.amount` lamports to `fee.address`. A token: `createAssociatedTokenAccountIdempotent` for `fee.address`'s associated token account (under the mint's token program), then `transferChecked` of `fee.amount` to it. A fee sent in a transaction of its own isn't found. |
    | Solana, a transaction RAVN builds (Mayan, Layerswap's memo route, Jupiter under 50 bps) | nothing: the execution has no `fee` | The fee is already inside `transaction.serialized`. Sign and send it as returned, from the signing wallet itself: a wallet that runs it inside its own program (a Squads-style smart account) pays it where RAVN can't see it. |

    The table is the short form of [Fees paid beside the swap](/pricing#fees-paid-beside-the-swap).
  </Step>

  <Step title="Report it on every status poll">
    Every [`/status`](/api-reference/status) call takes three things:

    * **`quoteToken`**: the one `/execute` returned, never the one from `/quote`. A two-hop route
      is rebound at execute.
    * **`ref`**: the `statusRef` from `/execute` when it has one; on `SIGNATURE`, the `statusRef`
      from `/submit-signature`; otherwise the hash of the swap transaction you broadcast (with
      `submit`, the `txHash` `/submit-transaction` returned).
    * **`txHash`**: the on-chain hash of the transaction that carried `fee.transaction`, whether
      its own or the batch's (never an EIP-5792 batch id or a 4337 `userOpHash`). On a two-hop route
      (`venue.id` is `compose`) with no fee transaction, the hop-1 transaction's hash. Not needed
      when the fee rode in the swap's own transaction and that hash is already your `ref`, or when
      the fee went inside a Bitcoin or Solana deposit: RAVN finds it there.

    `txHash` takes an EVM hash only (`0x` and 64 hex characters): `/status` answers
    `400 INVALID_REQUEST` to anything else, a Solana signature included, on every poll. A two-hop
    route whose hop 1 is on Solana or Bitcoin needs none: RAVN looks for hop 1 itself.

    Simplest: send `txHash` on **every** poll, from the first one. RAVN stops waiting for a fee a
    day after `/execute`; a fee reported later earns nothing.
  </Step>

  <Step title="Poll until the status is final">
    | `status` | What to do |
    | - | - |
    | `pending`, `processing` | Keep polling. A delivered swap stays `processing` for up to 15 minutes after `/execute` while RAVN can't yet read the fee transaction you reported. A failed status call (a `429`, a blip) changes nothing: retry it. |
    | `expired` | Keep polling, less often: usually a refund is on the way and the status becomes `refunded` (Across can take hours, Eco Routes up to about a week). An order that was never funded stays `expired`. |
    | `not_found` | Keep polling for a few minutes after sending: the venue may not have seen it yet. If it stays, you're polling with the wrong `quoteToken` or `ref`. |
    | `success`, `refunded`, `failed` | Final. Stop. |
    | `unknown` | The venue has no live tracker for this swap; polling won't change it. |

    This step matters even when the execution has no `fee`. On every `TRANSACTION` without a
    `statusRef`, RAVN only learns the swap's hash from your status poll, and on same-chain venues
    (0x Swap, 0x Solana, Nordstern, Fly Trade, KyberSwap, OKX DEX, Jupiter, Mayan same-chain) it
    checks that transaction on-chain before the swap counts. **A swap you never report never
    becomes payable.** See [Settlement](/api-reference/status#settlement).
  </Step>
</Steps>

<Tip>
  **On JS/TS, [`executeAndTrack`](/sdks/core#executeandtrack)** (`@ravnexchange/sdk` 0.2.0) does
  steps 2 to 4 for `TRANSACTION` and `SIGNATURE`: give it a `waitForReceipt` that returns the
  receipt, or it sends no fee. It polls through `expired` and `not_found`, retries a failed status
  call, and once anything is sent rejects only with an `ExecuteAndTrackError` whose `partial` holds
  every hash; persist them from `onProgress` so a crash never loses a swap. On a `DEPOSIT` it sends
  nothing: it returns `feePayment` (what to pay, see [depositFeePayment](/sdks/core#depositfeepayment))
  and `statusRef`; you send the deposit and the fee, then poll `getStatus(quoteToken, statusRef,
    feeTxHash)` yourself, retrying a failed call. 0.1.15 stopped polling at `expired` and `not_found`
  and lost the hashes on one failed status call: upgrade.
</Tip>

<Note>
  The [Quickstart](/quickstart) code does all four steps for an EVM wallet. Webhooks are no
  substitute for step 4: they fire only for swaps RAVN's own backstop settles, best-effort and
  never retried. See [Webhooks](/webhooks).
</Note>


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