Skip to main content
You’ll need: a trade API key for your app, your app id, fee recipients configured, and a non-zero app fee with self-custody fee collection enabled. Result: orders, webhooks, and the app fee attributed to your app. The market maker signs with their own wallet. You do not create their user first.
A builder code attributes venue volume. It does not place the trade on your Agg app, so it does not produce your Agg orders, order webhooks, or app fee. A trader key does. Give the market maker the key, the app id, and this page. They sign in as many wallets as they want, whenever they want. The first successful sign-in creates the user on your app. Later sign-ins mint a session for that same user. The user belongs to the app and the wallet, not to a key. Someone who signed in with a read or read_write key, or with no key, is the same user when they sign in with the trader key. Someone who first signed in with the trader key is the same user when they sign in with another of your keys. The token from either sign-in works with the other key. The key does not replace the user token and cannot act as a user who has not signed in. The key is trading access for your app only. It cannot list or read your other users, manage keys, members, settings, webhooks, or security, or set a per-trade fee or referral. It works only with your app id. skipQuote and skipBalance stay on read_write keys. Direct orders (POST /execution/orders) reject signingAddress, so this flow uses quote, then fill. Venue trader points stay on the market maker’s own venue account. Agg does not move those points to you. What you receive is the Agg order on your app, the order webhook, your app fee collected to feeRecipientEvm or feeRecipientHypercore, and your builder code when one is configured. Fee collection on this path works for a buy funded from one EVM wallet, with approveMode omitted or sponsored. Other shapes can skip the fee. See Self-custody trading.
New apps stay in testing mode until the partner agreement is signed: 20 users and 100 trades. A trader key does not raise those caps.

Create the key

In the admin dashboard, open API and create a key with the Trader permission. The secret is shown once. You can have three active trader keys. They do not count toward the five read and read/write keys. Revoking a key stops it on the next call and does not delete users it already created. To freeze one wallet, suspend that user.

Rate limits

Send the trader key on every call, including sign-in, quotes, and fills. The key has its own copy of your app’s server limits: 18,000 requests per minute on agg:rl:apikey:<keyId>, plus the per-endpoint API-key ceiling (quotes 1,500 per minute, trading 6,000 per minute) on agg:rl:route:v1:<group>:hash(key:<keyId>). Those calls do not count toward your app’s user buckets. A user token sent without the key is a normal user call. It uses the lower per-user ceilings and counts toward agg:rl:app:<appId>:user:<userId>. There is no single shared agg:rl:app:<appId> bucket.

Trade

The market maker keeps custody of the key. Agg never holds it. The signing wallet is the one that signed in, so there is no separate step to link it.
1

Sign in

POST /auth/start with provider: "siwe", x-app-id, and x-app-api-key. A valid trader key skips the per-IP sign-in limit and Turnstile. The key’s own rate limit still applies. Sign the nonce with the market maker’s EOA and POST /auth/verify. Keep the user access token.
2

Quote

GET /orderbook/{venueMarketOutcomeId}/route with the user token, the trader key, and signingAddress set to that EOA. Omit appFeeBips and referral fields. The app’s configured fee applies. A different address is refused.
3

Fill and sign

POST /execution/fill with the same signingAddress, then poll GET /execution/status?quoteId= and submit signatures. The sequence is the same as self-custody signing.
Limit orders and cancel use the same session. Cancel still needs cancelSignature. Kalshi still needs the user’s own venue key from Venue keys. The secret is never returned. GET /apps/{appId}/users and GET /apps/{appId}/orders return 403 for this key. A read key still has partner admin. Using the trader key with another app’s x-app-id returns 403.