Account Types

Lighter API users can operate under a Standard, Plus or Premium account.

Premium Account (Opt-in) -- Suitable for HFT, the lowest latency on Lighter. Part of volume quota program.

Latency for maker & cancel orders is 0ms. Fee credits also count as staked LIT for the parameters described in the table.

Staked LITsendTx/sendTxBatch per minuteMaker/Taker Fee DiscountMaker FeeTaker FeeTaker LatencySub-accounts
040000.0040%0.0280%140 ms64
1,00050002.5%0.0039%0.0273%140 ms64
3,00060005%0.0038%0.0266%140 ms64
10,000700010%0.0036%0.0252%140 ms64
30,000800015%0.0034%0.0238%140 ms64
100,0001200020%0.0032%0.0224%140 ms64
300,0002400025%0.0030%0.0210%140 ms64
500,0005760030%0.0028%0.0196%140 ms64

Plus Account (Opt-in) -- Suitable for latency-insensitive users, looking to get increased rate limits.

Access via the changeAccountTier endpoint.

Maker/Taker FeeTaker LatencyCancel/Modify LatencyMaker LatencysendTx/sendTxBatch per minuteRead-only weighted requests per minuteSub-accounts
0.005%300 ms300 ms0ms40002400016

Standard Account (Default) -- Suitable for retail and latency-insensitive traders.

Maker FeeTaker FeeTaker LatencyCancel/Modify LatencyMaker LatencySub-accounts
0%0%300 ms300 ms0ms4

For standard accounts only, TWAP orders charge a 1bps fee.

Account Switch

You can change your Account Type (tied to your L1 address) using the /changeAccountTier endpoint.

You may call that endpoint if at least 24 hours have passed since the last call. To upgrade account type, there is no cooldown.

Python snippet to switch tiers:

import asyncio
import logging
import lighter
import requests

logging.basicConfig(level=logging.DEBUG)

BASE_URL = "https://mainnet.zklighter.elliot.ai"

# You can get the values from the system_setup.py script
# API_KEY_PRIVATE_KEY =
# ACCOUNT_INDEX =
# API_KEY_INDEX =


async def main():
    client = lighter.SignerClient(
        url=BASE_URL,
        private_key=API_KEY_PRIVATE_KEY,
        account_index=ACCOUNT_INDEX,
        api_key_index=API_KEY_INDEX,
    )

    err = client.check_client()
    if err is not None:
        print(f"CheckClient error: {err}")
        return

    auth, err = client.create_auth_token_with_expiry(
        lighter.SignerClient.DEFAULT_10_MIN_AUTH_EXPIRY
    )

    response = requests.post(
        f"{BASE_URL}/api/v1/changeAccountTier",
        data={"account_index": ACCOUNT_INDEX, "new_tier": "premium"},
        headers={"Authorization": auth},
    )
    if response.status_code != 200:
        print(f"Error: {response.text}")
        return
    print(response.json())


if __name__ == "__main__":
    asyncio.run(main())
import asyncio
import logging
import lighter
import requests

logging.basicConfig(level=logging.DEBUG)

BASE_URL = "https://mainnet.zklighter.elliot.ai"

# You can get the values from the system_setup.py script
# API_KEY_PRIVATE_KEY =
# ACCOUNT_INDEX =
# API_KEY_INDEX =


async def main():
    client = lighter.SignerClient(
        url=BASE_URL,
        private_key=API_KEY_PRIVATE_KEY,
        account_index=ACCOUNT_INDEX,
        api_key_index=API_KEY_INDEX,
    )

    err = client.check_client()
    if err is not None:
        print(f"CheckClient error: {err}")
        return

    auth, err = client.create_auth_token_with_expiry(
        lighter.SignerClient.DEFAULT_10_MIN_AUTH_EXPIRY
    )

    response = requests.post(
        f"{BASE_URL}/api/v1/changeAccountTier",
        data={"account_index": ACCOUNT_INDEX, "new_tier": "standard"},
        headers={"Authorization": auth},
    )
    if response.status_code != 200:
        print(f"Error: {response.text}")
        return
    print(response.json())


if __name__ == "__main__":
    asyncio.run(main())

How fees are collected:

In isolated margin, fees are taken from the isolated position itself, but if needed, we automatically transfer from cross margin to keep the position healthy. In cross margin, fees are always deducted directly from the available cross balance.

Sub-accounts share the same tier as the main L1 address on the account.


Did this page help you?