Partner Attribution

This guide explains how partners can integrate with Lighter programmatically to earn additional fees for trades executed through their applications, or just for tracking purposes. The program is permissionless, allowing any account index to be used to collect fees, including subaccounts.


Definitions

Partner: You, the integrator building on top of Lighter.

Client: Your user, or customer, whose transactions you send on their behalf. Both standard and premium accounts are accepted.


Requirements

Trades containing partner attribution attributes with non-zero integrator fees will require the client submitting them to be on a Plus or Premium account type. To check the account type of a client, you can use the accountLimits endpoint. To change account type, use changeAccountTier. Zero-fee attribution (tracking only) works on any account type, including Standard.

Integrator Approval

Before you can append partner attributes to client transactions, they must submit a ApproveIntegrator transaction. Approving an account index associated with a different L1 address requires an L1 signature. However, if the account index is associated with the same L1 address, or fees are zero, only an L2 signature is needed. This transaction authorizes you to charge additional taker/maker fees on trades originating from orders created through your platform, as defined via the systemConfig endpoint.

At any point in time, there can only be a maximum of 4 approved Partners per Client.

Example

client.approve_integrator(
        eth_private_key=STRING,
        integrator_account_index=INTEGER,
        max_perps_taker_fee=INTEGER,
        max_perps_maker_fee=INTEGER,
        max_spot_taker_fee=INTEGER,
        max_spot_maker_fee=INTEGER,
        approval_expiry=INTEGER # in ms  
    )
client.approve_integrator(
        eth_private_key="",
        integrator_account_index=1234,
        max_perps_taker_fee=1000, # 10 bps
        max_perps_maker_fee=1000, # 10 bps
        max_spot_taker_fee=1000,  # 10 bps
        max_spot_maker_fee=1000,  # 10 bps
        approval_expiry=1775518466000 # in ms
    )
const tx = check(lighter.SignApproveIntegrator(
  PARTNER_ACCOUNT_INDEX,
  1000,   // maxPerpsTakerFee  (1000 = 10 bps)
  1000,   // maxPerpsMakerFee
  1000,   // maxSpotTakerFee
  1000,   // maxSpotMakerFee
  Date.now() + 365 * 24 * 3600e3, // approvalExpiry, unix ms
  0, await nextNonce(), API_KEY_INDEX, CLIENT_ACCOUNT_INDEX,
));

// If the partner account belongs to a different L1 address and fees > 0,
// the client's wallet must sign tx.messageToSign → txInfo.L1Sig

You can find the full Python example here. The TypeScript example uses the WASM signer from the TypeScript quickstart; see When an L1 signature is required. To revoke an integrator before the allowance expires, you can send another ApproveIntegrator request setting all fees to zero, requiring just an L2 signature.

Fields Explanation

IntegratorAccountIndex: Partner's account index. All partner fees collected from client trades will be credited to this account. For perpetual markets, the fees are paid and credited in USDC (perps). For spot markets, the fees are paid and credited in the received asset (e.g. buying spot ETH means the Client pays fees in ETH directly).

Max Fees: These values define the maximum fees you are allowed to charge your client.

Fees are calculated as:

fee(bps) = trade_size × (fee_value / 1e6)

Example:

MaxPerpsTakerFee = 500
500 / 1e6 = 0.0005 = 5 basis points

This means you can charge up to 5 bps of the trade quote for each perpetual taker order.

System-wide Maximums

Lighter enforces global maximum fee limits. If you submit an approval transaction exceeding these limits, the transaction will fail. Current limits can be checked via the systemConfig endpoint.

ApprovalExpiry

The timestamp when the integrator approval expires in a form of Unix timestamp in milliseconds. After this time, the partner must obtain approval again from the client.

The maximum value you can send is equivalent to 2^48-1.

Creating Orders for Your Client

Once the integrator approval is successfully submitted, you can begin sending transactions for the client and collecting partner fees.

When creating orders, include the following fields:

IntegratorAccountIndex: INTEGER # the partner account index, where integrator fees will accrue
IntegratorMakerFee: INTEGER     # fee the partner wants to charge for maker trades
IntegratorTakerFee: INTEGER     # fee the partner wants to charge for taker trades

These fees must not exceed the maximum values defined during the approval step. The same fields exist on modify and grouped orders.

🚧

Non-zero partner fees can't be combined with custom self-trade prevention

If an order sets a non-zero integratorTakerFee or integratorMakerFee together with any self-trade mode other than the default (0, 0: expire maker, same account index), it is rejected with 21159 "self-trade specifications are not allowed when there are non-zero fees". Zero-fee attribution (tracking only) works with any self-trade mode.

Example: Creating an Order

client.create_order(
        market_index=0,
        client_order_index=0, # bound to 2^48-1
        base_amount=1000,  # decimals as described in the orderBookDetails endpoint
        price=4050_00,  # decimals as described in the orderBookDetails endpoint
        is_ask=True, # sell
        order_type=client.ORDER_TYPE_LIMIT,
        time_in_force=client.ORDER_TIME_IN_FORCE_GOOD_TILL_TIME,
        reduce_only=False,
        trigger_price=0,
        integrator_account_index=integrator_account_index,
        integrator_taker_fee=integrator_taker_fee,
        integrator_maker_fee=integrator_maker_fee,
        nonce=nonce,
        api_key_index=api_key_index,
    )
lighter.SignCreateOrder(
  marketIndex, clientOrderIndex, baseAmount, price, isAsk, orderType, tif,
  reduceOnly, triggerPrice, orderExpiry,
  PARTNER_ACCOUNT_INDEX, // integratorAccountIndex
  500,                   // integratorTakerFee (5 bps) – must be ≤ approved max
  200,                   // integratorMakerFee (2 bps)
  0, 0, 0, nonce, API_KEY_INDEX, CLIENT_ACCOUNT_INDEX,
);

You can find the full Python example here.

Design tips

  • Show your fee clearly in the order ticket.
  • Request an approval expiry that matches your product (e.g. 1 year) and re-prompt before it lapses.
  • Use a dedicated sub-account as your integrator account to keep revenue separate.
  • Track attributed volume and fees with partnerStats.

Did this page help you?