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

# Deployer Fees

> Read token-attributed deployer balances and claim SOL revenue through dedicated deployer endpoints

New SOL fee-share v2 configurations reserve a separate share for the wallet that pays to create the config. The deployer receives **25% of the gross claimers pool**, before that pool is divided among the configured fee recipients.

This applies to newly created configs through [Create Fee Share Config](/api-reference/create-fee-share-configuration). Existing configs returned with `needsCreation: false` retain their existing terms. Legacy configs, v1-to-v2 migrations, Robinhood Chain launches, and [non-SOL direct launches](/how-to-guides/launch-token-non-sol-quote) have separate behavior.

## Choose the config payer deliberately

The `payer` supplied to `POST /fee-share/config` becomes the deployer. There is no public request field to select a different deployer or change its fee rate. A different wallet used later to launch the token does not replace the config's deployer.

The `claimersArray` and `basisPointsArray` still define the normal recipient allocation, and basis points must sum to **10,000**. Those percentages divide the claimers pool remaining after the deployer deduction. Do not reduce the array total to 7,500 to reserve the deployer share.

The payer can also appear in `claimersArray`. In that case, it earns both its separate deployer cut and its normal recipient allocation. Config creation also funds the required deployer accounts, so its SOL cost can differ from a legacy config.

## Calculate the split

The deployer rate is 2,500 basis points of the **gross claimers pool**, not 25% of total trading fees. First account for any fee compounding and the applicable platform split. The deployer then takes 25% of the gross claimers pool, and the configured recipients divide the remaining 75%. A partner share, when present, is deducted from the **platform pool** — it does not reduce the deployer or recipient amounts.

For a protocol claim of 1 SOL, assuming a 50% platform split and a partner taking 25% of the platform pool:

| Recipient                          |   SOL |
| ---------------------------------- | ----: |
| Platform                           | 0.375 |
| Partner (25% of the platform pool) | 0.125 |
| Separate deployer share            | 0.125 |
| Pool divided by `basisPointsArray` | 0.375 |

If there is no partner, the partner share stays with the platform, which then receives the full 0.5 SOL. The deployer share (0.125 SOL) and the recipient pool (0.375 SOL) are the same either way; do not deduct the partner share from the claimers pool.

If the deployer has a 50% normal allocation and another recipient has the other 50%, the example above pays the deployer 0.3125 SOL in total and the other recipient 0.1875 SOL. Allocating 100% of the normal recipient pool to another wallet still leaves the separate deployer share in place.

Actual calculations use integer lamports and round each percentage down. Platform overrides and compounding can change the amounts; see [Customize Token Fees](/how-to-guides/customize-token-fees) for the gross fee pools.

## Read deployer balances

Use [Get Deployer Claimable Positions](/api-reference/get-deployer-claimable-positions), authenticated with your `x-api-key`:

```http theme={null}
GET https://public-api-v2.bags.fm/api/v1/fee-share/deployer/claimable-positions?wallet=DEPLOYER_WALLET
x-api-key: YOUR_API_KEY
```

The `wallet` is the config payer. It can claim its separate deployer share even if every normal recipient allocation belongs to other wallets. Pending pool discovery uses indexed config-creator and launch metadata, then verifies the deployer on-chain. Configs created outside the Bags API need matching indexed metadata to appear before their first protocol claim.

The response separates fees still pending in each token's pools from fees already credited to the deployer's shared WSOL vault. The accrued portion is attributed using indexed events and reconciled with finalized on-chain state. Pool calculations use fresh finalized config rates, including current deployer terms. Successful GET results can be cached for 5 seconds with a 2-second stale window.

```json theme={null}
{
  "success": true,
  "response": {
    "wallet": "DEPLOYER_WALLET",
    "quoteMint": "So11111111111111111111111111111111111111112",
    "positions": [
      {
        "tokenMint": "TOKEN_MINT_A",
        "pendingDbcLamports": "1000000",
        "pendingDammLamports": "2000000",
        "accruedLamports": "3000000",
        "totalClaimableLamports": "6000000"
      },
      {
        "tokenMint": "TOKEN_MINT_B",
        "pendingDbcLamports": "0",
        "pendingDammLamports": "0",
        "accruedLamports": "4000000",
        "totalClaimableLamports": "4000000"
      }
    ],
    "vaultClaimableLamports": "7500000",
    "unattributedVaultLamports": "500000",
    "totalClaimableLamports": "10500000"
  }
}
```

All amounts are **decimal lamport strings**. Use `BigInt` for arithmetic:

```typescript theme={null}
const tokenTotal = positions.reduce(
  (sum, position) => sum + BigInt(position.totalClaimableLamports),
  BigInt(0)
);
const walletTotal = tokenTotal + BigInt(unattributedVaultLamports);
```

Each position's total is `pendingDbcLamports + pendingDammLamports + accruedLamports`. The wallet total adds those position totals and `unattributedVaultLamports` once. **Do not add `vaultClaimableLamports` again**: its attributed portion is already included in the positions, and its residual is the separate unattributed field.

The unattributed field covers vault funds without recorded token fee accrual, such as direct deposits. It is never assigned to an arbitrary token. Only positions with positive totals are returned, ordered by `tokenMint`. A wallet can have an empty `positions` array and a positive unattributed vault balance.

<Note>
  If indexed attribution is incomplete or cannot be reconciled, the endpoint returns `503` with `Retry-After: 5` and `{ "success": false, "response": "..." }`. Treat the balance as temporarily unavailable; do not display it as zero. Discovery and accounting limits also reject incomplete results rather than return partial totals.
</Note>

## Request a deployer claim batch

Call [Create Deployer Claim Transactions](/api-reference/create-deployer-claim-transactions):

```http theme={null}
POST https://public-api-v2.bags.fm/api/v1/fee-share/deployer/claim-txs
x-api-key: YOUR_API_KEY
Content-Type: application/json

{
  "wallet": "DEPLOYER_WALLET",
  "maxTransactions": 10
}
```

`wallet` is required and must sign the returned transactions. An API key authorizes the HTTP request; it does not authorize moving the wallet's funds. These endpoints are REST calls; this guide does not require a new SDK method.

Optional parameters:

| Field             | Behavior                                                                                                                |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `tokenMints`      | Filter pending pool collection to 1–20 base mints. Omit to consider all discovered tokens.                              |
| `maxTransactions` | Return at most this many transactions, from 1–20; defaults to 10. Deferred candidates do not consume transaction slots. |

A request attempts at most 20 pool claim candidates, independently of `maxTransactions`. Claims beyond either limit are deferred with `batch_limit`. Optional request fields must be omitted when unused; `null` is not accepted.

Each pool claim collects the token's deployer cut and withdraws the shared deployer vault. A vault-only withdrawal is also supported when fees are already accrued. Withdrawals unwrap WSOL into native SOL for the deployer. They do not withdraw the wallet's normal recipient ledger or user fee vault.

<Warning>
  Every vault withdrawal is wallet-wide. `tokenMints` limits which pools are collected; it does not restrict the accrued vault balance being withdrawn. A request filtered to token A can still withdraw accrued deployer revenue from tokens B and C.
</Warning>

The gas sponsor partially signs and fronts funds for execution. The transaction repays sponsorship and execution costs from claim proceeds; existing wallet SOL must cover a shortfall. The planner reserves wallet funds conservatively and does not assume that profits from an earlier transaction will fund a later one, or count the same aggregate vault balance twice.

The response is a plan:

```json theme={null}
{
  "success": true,
  "response": {
    "wallet": "DEPLOYER_WALLET",
    "quoteMint": "So11111111111111111111111111111111111111112",
    "transactions": [
      {
        "transaction": "BASE58_VERSION_0_TRANSACTION",
        "blockhash": {
          "blockhash": "RECENT_BLOCKHASH",
          "lastValidBlockHeight": 123456789
        }
      }
    ],
    "remainingTokenMints": ["TOKEN_MINT_B"],
    "deferredClaims": [
      {
        "tokenMint": "TOKEN_MINT_B",
        "protocol": "dammV2",
        "reason": "needs_wallet_sol",
        "additionalSolLamports": "100000"
      }
    ],
    "transactionVersion": 0
  }
}
```

Every transaction item uses the **`transaction`** field and the shared `TransactionWithBlockhash` shape. These are version-0 transactions; the legacy creator claim response's `tx` field is a different contract.

A successful HTTP response does not mean every claim fits into this batch. Inspect `deferredClaims`, including when `transactions` is empty:

| Reason              | Next step                                                                                                                                                                          |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `needs_wallet_sol`  | Add sufficient SOL to the deployer wallet, using `additionalSolLamports` when supplied as the estimated shortfall, then request a fresh plan.                                      |
| `simulation_failed` | The claim could not be simulated successfully. Refresh the state and request a fresh plan before attempting it.                                                                    |
| `batch_limit`       | Confirm any returned transactions, then request another plan for the remaining tokens. A request may reach the 20-candidate attempt cap even when fewer transactions are returned. |

`remainingTokenMints` lists selected tokens whose pending pool claims were deferred. Tokens omitted by a `tokenMints` filter are not listed. A vault-only deferral has `tokenMint: null`, `protocol: "vault"`, and may leave `remainingTokenMints` empty.

## Sign and submit version-0 transactions

This example uses a local Solana keypair. A wallet adapter can supply the signature instead. Keep the returned message, blockhash, and sponsor signature intact.

```typescript theme={null}
import { Connection, Keypair, VersionedTransaction } from "@solana/web3.js";
import bs58 from "bs58";

type ClaimPlan = {
  transactions: {
    transaction: string;
    blockhash: { blockhash: string; lastValidBlockHeight: number };
  }[];
  remainingTokenMints: string[];
  deferredClaims: {
    tokenMint: string | null;
    protocol: "dbc" | "dammV2" | "vault";
    reason: "needs_wallet_sol" | "simulation_failed" | "batch_limit";
    additionalSolLamports?: string;
  }[];
  transactionVersion: 0;
};

async function claimDeployerBatch(
  connection: Connection,
  wallet: Keypair,
  apiKey: string
): Promise<ClaimPlan> {
  const response = await fetch(
    "https://public-api-v2.bags.fm/api/v1/fee-share/deployer/claim-txs",
    {
      method: "POST",
      headers: { "x-api-key": apiKey, "Content-Type": "application/json" },
      body: JSON.stringify({ wallet: wallet.publicKey.toBase58(), maxTransactions: 10 })
    }
  );
  const payload = await response.json();
  if (!response.ok || !payload.success) {
    throw new Error(payload.error ?? payload.response ?? "Claim plan unavailable");
  }
  const plan = payload.response as ClaimPlan;

  for (const item of plan.transactions) {
    const transaction = VersionedTransaction.deserialize(bs58.decode(item.transaction));
    // Add the wallet signature; retain the existing sponsor signature.
    transaction.sign([wallet]);
    const signature = await connection.sendRawTransaction(transaction.serialize());
    const confirmation = await connection.confirmTransaction(
      { signature, ...item.blockhash },
      "confirmed"
    );
    if (confirmation.value.err) {
      throw new Error(`Deployer claim failed: ${JSON.stringify(confirmation.value.err)}`);
    }
  }

  return plan;
}
```

After confirming the batch, fetch balances and request a fresh plan for any remaining claims. Finalized balance reads may take longer to reflect a just-confirmed transaction. If a transaction expires or fails, stop the batch and request a new plan after checking its status; do not replace its blockhash or discard its partial signatures. Funding-related deferrals need the wallet top-up before retrying.

## Keep creator and deployer accounting separate

[Get Claimable Positions](/api-reference/get-claimable-positions) and the existing [v2](/api-reference/get-claim-transactions) / [v3](/api-reference/get-claim-transactions-v3) creator claim endpoints cover normal recipient earnings and user fee vaults. They do not include or automatically withdraw the separate deployer share. A wallet in both roles uses both flows.

A creator protocol claim can credit deployer fees to the shared vault, but withdrawing them uses the dedicated deployer endpoint. Token lifetime fees, creator claim-event feeds, and creator claim statistics are not a complete deployer earnings history. The new GET endpoint reports currently unclaimed deployer revenue, not lifetime earnings.
