Who can copy
Copying always happens in the name of one of your users:- a platform user, by
external_idorcsid_id, - or a person who signed in to your app with CabalSpy ID and granted the scope
trade_feed, bycsid_id.
How it works
1
The user switches copying on
Your backend calls POST /v1/copy-trading/settings with the user, the trader and how much to copy. From now on your instance copies this trader for this user.
2
The trader trades
CabalSpy ID sees the trade on one of the trader’s verified wallets, the same moment it reaches the Trade Feed.
3
CabalSpy ID sends an instruction
For each user who copies the trader, CabalSpy ID sizes the trade by the user’s settings and sends a copy instruction as the
copy_trade.instruction webhook and on the copy trading stream. You can also poll GET /v1/copy-trading/instructions.4
Your app executes it
Within 120 seconds, your app swaps with the user’s wallet, respecting
max_price_usd (buys) or min_price_usd (sells).5
Your app reports the result
Call POST /v1/copy-trading/instructions/status with
executed, failed or skipped, and the transaction signature when there is one. The result decides whether later sells of that token are copied.One platform at a time
A user can use several platforms with CabalSpy ID, but each trader is copied by one platform at a time, so a user is never copied twice. The platform that switches copying on for a trader receives that trader’s instructions for that user, and nobody else does. While your platform copies a trader for a user, another platform cannot switch copying on for the same trader and gets 409 copy_managed_elsewhere. It seesmanaged_by_other_platform: true in GET /v1/copy-trading/settings. Once the first platform switches copying off, another platform can take over.
Sizing
Each user has their own settings per trader. See Copy settings for all fields and limits. Buys. The amount in USD comes frommode:
max_usd, if set, caps every buy. Buys that come out below $1 are not sent. The instruction carries the amount in USD (amount_usd) and, where the price of the chain’s native coin is known, in the native coin (amount_native, for example SOL).
Sells. With sides: "both" (default), sells are copied as a share of the user’s copied position, not as an amount:
- The trader sold part of their position: sell the same share. A trader who sold 50 % of their tokens sends
sell_percent: 50. - The trader closed their position:
sell_percent: 100. - A sell is only sent when the user has a copied buy in that token from that trader that you did not report as
failedorskipped. A user who never copied the entry does not get the exit. - Sells whose entry is unknown, for example of tokens the trader bought before CabalSpy ID tracked their wallet, are not copied.
sides: "buys", only buys are copied and the user decides when to sell.
Price limit. Every instruction carries the trader’s price (price_usd) and the user’s slippage (slippage_bps, default 300 = 3 %). For a buy, max_price_usd is the trader’s price plus the slippage, for a sell min_price_usd is the trader’s price minus the slippage. Do not execute beyond that limit; report skipped instead.
Example. A user copies with mode: "fixed_usd", amount_usd: 25 and max_usd: 20. The trader buys 1,000 tokens for 1 SOL ($150), so at $0.15 per token. The user’s instruction: buy for **$20** (capped), 0.133333333 SOL, at most $0.1545 per token (+3 %).
Copying does not depend on the user’s alert filters. A trader the user muted in their Trade Feed, or with buy or sell alerts off or a minimum trade size, is still copied in full.
The instruction
One instruction per user and trade. The same trade is never sent twice for the same user: theid is fixed per user and trade, so deduplicate on it.
copy_trade.instruction
"side": "sell", sell_percent set, amount_usd and amount_native null and min_price_usd instead of max_price_usd:
action of a sell
string
The instruction id, fixed per user and trade. Deduplicate on it.
string
Always
copy_instruction.string
When the instruction was made, and until when it is meant to be executed: 120 seconds later.
string
The user who copies.
string
Your own id of the user when they are a platform user, otherwise null. Only in the webhook and on the stream; look the user up by
csid_id in REST responses.object
The trader who traded: csid_id, username, name, image_url, kol and profile_url. username and profile_url are null for platform users.
object
What to execute.
object
The trader’s own trade, the same trade object as in the Trade Feed: side, label (
new, add, partial, close), sold_percent, amounts in the native coin and USD, token amount, price, realized PnL of a sell, the trader’s wallet and the transaction with explorer links.object
The user’s copy settings for this trader at the time of the instruction.
object
token (the token page), terminal (the CabalSpy Terminal on Solana and BNB Chain, otherwise null) and profile (the trader’s profile).
string
What your app reported, see Report the result. Null until then.
string
When the instruction was made or last reported.
Statuses
executed, failed and skipped are final. A copied buy reported as failed or skipped means later sells of that token are not copied for that user. A buy still pending or expired counts as a position.
Quickstart
1
Switch copying on
Copy
@MazeCCC for one of your platform users with $25 per buy, at most $20:2
Receive instructions
Subscribe your webhook to
copy_trade.instruction on the instance’s Webhooks tab, or connect to the copy trading stream. Verify the signature as described in Webhooks and answer 2xx right away.3
Execute
Look up the user by
external_id or csid_id, check expires_at, and swap with their wallet within the price limit. For sells, sell sell_percent % of what the user holds from their copied buys of this token.4
Report
Report every instruction, also the ones you did not execute.
GET /v1/copy-trading/instructions?status=pending and decide whether to execute or skip each one.
Stopping
Copying of a trader stops for a user when:- you switch it off with
"enabled": falsein POST /v1/copy-trading/settings, - the trader is removed from the user’s Trade Feed,
- the user revokes your app’s access or the scope
trade_feed, or falls outside your plan’s user limit, - the trader makes their trading private.

