Skip to content

Triggers

Triggers are webhook-based trade automations. You define a trigger with your trade parameters, then fire it from TradingView alerts, custom bots, or any system that can send an HTTP POST request.

How Triggers Work

  1. You create a trigger in the Crodl UI with your desired trade parameters
  2. You copy the trigger's JSON payload (which includes your security token) and the webhook URL
  3. You configure an external source (e.g., TradingView) to POST the trigger payload to the webhook
  4. Crodl validates the payload, resolves your API key via the security token, and queues the trade for execution on your exchange
  5. If the payload includes strategy_dashboard_id, Crodl also groups the execution into that strategy journal for dashboard reporting
  6. You receive a 202 Accepted response immediately — execution happens asynchronously in the background. Results show up in the Executed Triggers tab and via Discord/Telegram notifications if connected

Webhook Endpoint

All triggers are sent to a single endpoint:

POST https://api.crodl.com/webhooks/trading
Content-Type: application/json

The response is immediate:

{
  "accepted": true,
  "request_id": "a1b2c3d4...",
  "accepted_ms": 45
}

202 Accepted means the request was validated and queued — not that the order filled. Check the Executed Triggers tab or your Discord/Telegram notifications for the execution result.

Security Token

Every trigger payload requires a security_token. This is a unique key tied to your exchange API key — it authenticates the webhook without exposing your actual API credentials.

To get it, use Copy JSON on any trigger row on the Automations page — the copied payload includes the security_token for that trigger's API key. MCP clients can retrieve it with the single-trigger payload tool using explicit token reveal.

If you are connecting Claude, Codex, or another MCP client, use MCP Access instead of pasting security_token into trade requests. MCP tools use the same payload shape and inject the token server-side. If you explicitly ask for one saved trigger's TradingView payload, MCP can return that trigger's security_token so you can copy it into TradingView.

Open Trigger

An open trigger places a new position. Here's a full example:

{
  "name": "BTC Long",
  "allocation_id": "btc-breakout-a1",
  "strategy_dashboard_id": "btc-momentum-2026",
  "exchange": "blofin",
  "trading_action": "open",
  "security_token": "your_security_token",
  "symbol": "BTC-USDT",
  "side": "long",
  "order_type": "market",
  "margin_mode": "cross",
  "position_mode": "oneway",
  "trading_type": "futures",
  "leverage_amount": "10",
  "quantity_type": "percentage",
  "quantity_amount": "5",
  "quantity_quote": "USDT",
  "opposite_side_close": false
}

Open Trigger Fields

FieldRequiredValuesDescription
exchangeYesblofin, bitunix, bybit, bitget, okx, hyperliquidTarget exchange
trading_actionYesopenOpens a new position
security_tokenYesstringYour API key's security token
symbolYese.g. BTC-USDT, BTC-USDT-SWAPTrading pair
sideYeslong, shortTrade direction
order_typeYesmarket, limit, post_only, fok, iocOrder execution type. There is no chase value — Limit Chaser is Terminal-only
quantity_typeYes*amount, percentage, assetHow quantity is measured
quantity_amountYes*numeric stringSize of the trade (percentage must be in (0, 100])
qtyYes*number or numeric stringShorthand alternative to the two fields above — a raw size in base units. Crodl treats it as quantity_type: "asset" and takes the absolute value. Ignored if quantity_type and quantity_amount are both present
margin_modeNoisolated, crossMargin mode. Defaults to isolated
position_modeNooneway, hedgePosition mode. Defaults to oneway
leverage_amountNonumeric stringLeverage multiplier (e.g. "10"), up to the pair's maximum. If omitted, your current leverage on the exchange is kept
quantity_quoteNoUSDT, USDC, USDQuote currency (auto-derived from the symbol if omitted)
quantity_modeNomargin, positionWhether an amount quantity is margin or position notional
max_notional_usdNonumeric stringOptional maximum position notional in USD terms
guard_actionNoreject, clampWhat to do when max_notional_usd is exceeded. Defaults to reject
nameNostringLabel for this trigger
allocation_idNostringOptional strategy bucket ID for tracking this position independently from other strategies on the same symbol/side. Market orders only
strategy_dashboard_idNostringOptional reporting-only journal ID used to group trades into one strategy dashboard
trading_typeNofuturesDefaults to futures (the only supported value). market_type is accepted as an alias

* Send either quantity_type + quantity_amount, or qty. A payload with none of them is rejected with 422.

OKX symbols should use the full exchange-native instId format, for example BTC-USDT-SWAP for linear perpetuals or BTC-USD-SWAP for inverse perpetuals.

Hyperliquid does not support hedge mode — sending position_mode: "hedge" to Hyperliquid fails with position_mode_unsupported. Hyperliquid also has no FOK policy on this order path: order_type: "fok" is rejected at admission on both opens and closes (hyperliquid_fok_unsupported / hyperliquid_close_fok_unsupported). Use ioc or post_only instead.

Optional Trade Guardrails

Open triggers can include optional guard fields to prevent a signal from placing a larger position than expected. They work on every supported exchange: Blofin, Bitunix, Bybit, Bitget, OKX, and Hyperliquid. If these fields are omitted, Crodl keeps the existing behavior and does not enforce a notional cap.

These are payload-only fields — the trigger form does not expose them. Add them to the JSON you send (or paste into TradingView):

"max_notional_usd": "500",
"guard_action": "reject"

That snippet is two fields to add to an existing payload, not a payload on its own. Every webhook request must be one complete JSON object containing at minimum exchange, trading_action, security_token, symbol, side, order_type, and the quantity fields — see the full example above.

max_notional_usd is a position notional cap, not the margin spent. For example, a 10 SOL order at $100 is about $1,000 notional even if the trade uses 10x leverage and only requires about $100 margin.

FieldBehavior
max_notional_usdCaps the final computed order notional before Crodl submits the order to the exchange
guard_action: "reject"Rejects the trade before exchange submission if the cap is exceeded
guard_action: "clamp"Reduces the computed quantity to fit the cap, then submits the smaller order

If guard_action is omitted but max_notional_usd is present, Crodl defaults to reject.

If clamp reduces the quantity below the exchange minimum order size, Crodl rejects the trade instead of submitting an invalid order.

These guardrails apply only to open triggers. Close triggers ignore these fields so exits are not blocked by notional caps.

Close Trigger

A close trigger reduces or closes an existing position:

{
  "name": "BTC Close Half",
  "allocation_id": "btc-breakout-a1",
  "strategy_dashboard_id": "btc-momentum-2026",
  "exchange": "blofin",
  "trading_action": "close",
  "security_token": "your_security_token",
  "symbol": "BTC-USDT",
  "side": "close_long",
  "order_type": "market",
  "trading_type": "futures",
  "quantity_type": "percentage",
  "quantity_amount": "50",
  "cancel_unfilled": "disabled"
}

Close Trigger Fields

FieldRequiredValuesDescription
trading_actionYescloseCloses a position
sideYesclose_long, close_shortWhich position to close (long/short/buy/sell are accepted as aliases)
quantity_typeYesamount, percentage, assetHow quantity is measured
quantity_amountYesnumeric stringAmount to close (e.g. "50" for 50%)
order_typeYesmarket, limit, post_only, fok, iocOrder execution type
allocation_idNostringOptional strategy bucket ID to close only one allocation instead of the full net position. Market orders only
strategy_dashboard_idNostringOptional reporting-only journal ID used to group this close with the matching strategy dashboard
cancel_unfilledNodisabled, enabled, longs, shorts, bothCancel pending orders before closing. Defaults to disabled

Setting quantity_amount to "100" with quantity_type of "percentage" will close the entire position.

Flat Trigger (Blofin only)

trading_action: "flat" is a shorthand for "close everything on the opposite side". Crodl rewrites it into a full close before execution:

  • side: "buy" or "long" → closes your short (close_short)
  • side: "sell" or "short" → closes your long (close_long)
  • quantity_type defaults to percentage and quantity_amount to 100 if you omit them
{
  "exchange": "blofin",
  "trading_action": "flat",
  "security_token": "your_security_token",
  "symbol": "BTC-USDT",
  "side": "sell",
  "order_type": "market"
}

flat is Blofin-only. Sending it to any other exchange fails with 422 and the message Flat trading_action is only supported for Blofin. On other exchanges use trading_action: "close" with quantity_type: "percentage" and quantity_amount: "100".

allocation_id

allocation_id is an optional strategy bucket ID for running multiple strategies on the same symbol and side without mixing their closes together.

When allocation_id is present:

  • Opens are tracked into that allocation bucket
  • Multiple opens with the same allocation_id accumulate into the same bucket
  • Closes only consume that bucket's remaining size
  • Percentage closes are calculated from that allocation's remainder, not the full net exchange position

When allocation_id is omitted, Crodl keeps the legacy behavior and closes against the normal net position on the exchange.

You can review your allocation buckets (opened and remaining size per ID) in the Allocation IDs tab on the Automations page.

Example flow

Open $100 of notional into the btc-breakout-a1 bucket:

{
  "exchange": "blofin",
  "trading_action": "open",
  "security_token": "your_security_token",
  "symbol": "BTC-USDT",
  "side": "long",
  "order_type": "market",
  "allocation_id": "btc-breakout-a1",
  "quantity_type": "amount",
  "quantity_mode": "position",
  "quantity_amount": "100"
}

Then close 10% of that bucket:

{
  "exchange": "blofin",
  "trading_action": "close",
  "security_token": "your_security_token",
  "symbol": "BTC-USDT",
  "side": "close_long",
  "order_type": "market",
  "allocation_id": "btc-breakout-a1",
  "quantity_type": "percentage",
  "quantity_amount": "10"
}

In that example, Crodl closes 10% of the btc-breakout-a1 allocation only. The rest of that allocation stays open, and any other allocation on BTC-USDT is untouched.

allocation_id requires order_type: "market" — on both opens and closes. Any other order type is rejected with allocation_orders_market_only.

strategy_dashboard_id

strategy_dashboard_id is an optional reporting-only ID for journaling and dashboarding.

Use it when you want to group open and close triggers into a strategy journal without affecting how the trade is executed.

When strategy_dashboard_id is present:

  • Crodl records the value for reporting and dashboard views
  • Crodl auto-creates the journal the first time that ID is saved or executed for that exchange and API key
  • The trade execution path does not change
  • Closes still follow the same allocation_id and position rules as before

You can review those journals in Dashboard → Strategy or directly at /dashboard?view=strategy. In that view, you:

  • Pick the exchange first
  • Pick the API key
  • Choose the exact strategy_dashboard_id journal to review
  • Rename, annotate, end, or delete the journal without changing how trades execute

Choosing a good ID

Use an ID that stays stable across the related opens and closes for one strategy run. Good examples:

  • btc-breakout-london
  • turbo-venom
  • eth-mean-revert-apr-2026

If you want a different journal, send a different strategy_dashboard_id.

Do not use strategy_dashboard_id as a substitute for allocation_id. allocation_id controls how closes are matched; strategy_dashboard_id only groups trades for reporting.

You can use strategy_dashboard_id without allocation_id if you only want journal reporting. Add both fields when you want isolated close matching and grouped reporting at the same time.

Limit Order Pricing

For non-market order types (limit, post_only, fok, ioc), two additional fields are required:

FieldValuesDescription
limit_price_modeprice, percentageAbsolute price or percentage-based
limit_order_pricenumeric stringThe price or percentage value

Both are fields you add to an open or close payload — not payloads on their own.

Example — limit order at a specific price:

"order_type": "limit",
"limit_price_mode": "price",
"limit_order_price": "95000"

Example — limit order 2% below current price:

"order_type": "limit",
"limit_price_mode": "percentage",
"limit_order_price": "98"

Sending a non-market order_type without both limit_price_mode and limit_order_price is rejected with 422. For order_type: "market", Crodl ignores and clears both fields.

Take-Profit and Stop-Loss

Attach TP/SL to any open trigger. All TP/SL fields are optional — omit them entirely if you don't want TP/SL. TP and SL are independent: you can send either one, or both.

Take-Profit Fields

FieldValuesDescription
take_profit_typemarket, limitTP execution type — setting this enables the TP
take_profit_trigger_pricenumeric stringPrice that activates the TP
take_profit_modeprice, percentageAbsolute or percentage-based. Defaults to price
take_profit_order_pricenumeric stringExecution price (required if type is limit)

Stop-Loss Fields

FieldValuesDescription
stop_loss_typemarket, limitSL execution type — setting this enables the SL
stop_loss_trigger_pricenumeric stringPrice that activates the SL
stop_loss_modeprice, percentageAbsolute or percentage-based. Defaults to price
stop_loss_order_pricenumeric stringExecution price (required if type is limit)

Example with TP/SL

{
  "exchange": "blofin",
  "trading_action": "open",
  "security_token": "your_token",
  "symbol": "ETH-USDT",
  "side": "long",
  "order_type": "market",
  "margin_mode": "cross",
  "position_mode": "oneway",
  "leverage_amount": "5",
  "quantity_type": "percentage",
  "quantity_amount": "10",
  "take_profit_type": "market",
  "take_profit_mode": "price",
  "take_profit_trigger_price": "4000",
  "stop_loss_type": "market",
  "stop_loss_mode": "price",
  "stop_loss_trigger_price": "3200"
}

If you use allocation_id together with TP/SL, the TP/SL remains position-level, not allocation-level. That means one TP/SL can affect every allocation sharing the same symbol and side.

Trade Policies

opposite_side_close

When true, automatically closes any existing position on the opposite side before opening the new one.

Example: You hold a SHORT on BTC-USDT and send an open LONG trigger with "opposite_side_close": true — the SHORT is closed first, then the LONG is opened.

cancel_unfilled

Controls whether pending unfilled orders are cancelled before the trigger executes:

ValueBehavior
disabledDo nothing (default)
enabledCancel all unfilled orders on this symbol
longsCancel only long orders
shortsCancel only short orders
bothCancel both long and short orders

pyramiding_allowed

Controls whether multiple orders or positions can stack on the same symbol and side:

ValueBehavior
noneBlock if a matching order or position already exists (default)
orders_and_positionsAllow unlimited stacking
orders_onlyAllow pending orders, block new positions
positions_onlyAllow new positions, block pending orders

Use pyramiding_allowed: "none" (the default) to prevent accidentally opening duplicate positions from repeated alerts.

TradingView Integration

Connect your triggers to TradingView alerts:

  1. Create a trigger in Crodl and copy the JSON payload
  2. In TradingView, create an alert on your desired condition
  3. In the alert's Notifications tab, enable Webhook URL
  4. Set the URL to https://api.crodl.com/webhooks/trading
  5. Paste your trigger JSON into the Message field
  6. Save the alert

When TradingView fires the alert, it POSTs your payload to Crodl, which executes the trade on your exchange.

You can use TradingView's placeholder variables (like {{ticker}}, {{close}}) in the JSON message to make dynamic triggers that adapt to market conditions.

Execution Flow

When a trigger fires, Crodl processes it in this order:

  1. Validate payload and resolve security token
  2. Return 202 Accepted immediately
  3. Cancel unfilled orders (if cancel_unfilled is set)
  4. Close opposite position (if opposite_side_close is true)
  5. Check pyramiding rules (if pyramiding_allowed restricts)
  6. Apply optional open-trade guardrails (if max_notional_usd is set)
  7. Place the order on your exchange
  8. Record execution result in your trade history

Because execution is asynchronous, the webhook response never contains a fill result. Track outcomes in the Executed Triggers tab, or connect Discord/Telegram in Settings to get a notification per execution.

Response Codes

CodeMeaning
202Trigger accepted and queued for execution
400Invalid JSON or unsupported exchange
401Invalid security token
409An allocation close for the same bucket is already in progress
422Validation error (missing or invalid fields)
429Rate limited (max 30 requests/second)
503Queue or idempotency backend temporarily unavailable, or the same request is still being claimed — retry

Idempotency

Crodl supports idempotent trigger execution to prevent duplicate trades from repeated webhook fires.

How It Works

When you send a trigger with an explicit request key, Crodl checks whether that key has already been accepted.

  • Explicit keys use a 1-hour TTL window
  • If no explicit key is provided, each webhook request is treated as a new request

If a matching request is found, the original request ID is returned instead of executing a new trade.

Providing an Idempotency Key

You can provide an idempotency key in two ways (checked in this order):

1. HTTP Header

Idempotency-Key: your-unique-key-here

2. Body-level key — include any of these fields in your JSON payload:

FieldAlso accepts (camelCase)
idempotency_keyidempotencyKey
request_idrequestId
signal_idsignalId
alert_idalertId
{
  "exchange": "blofin",
  "trading_action": "open",
  "security_token": "your_token",
  "idempotency_key": "tv-alert-btc-long-20240115-001",
  "symbol": "BTC-USDT",
  "side": "long",
  "order_type": "market",
  "quantity_type": "percentage",
  "quantity_amount": "5"
}

Response Headers

Responses include idempotency information:

HeaderDescription
X-IdempotencyIdempotency decision (claimed, replay, or bypass)
X-Idempotency-SourceWhere the key came from (header, body, or request when no explicit key was provided)

Always provide an explicit idempotency key when sending triggers from TradingView or other alert systems that may fire multiple times. This prevents duplicate trades from repeated alerts.

Managing Triggers

On the Automations page (/trading-terminal):

  • Create open and close triggers with a visual form
  • Edit existing triggers to update parameters
  • Delete triggers you no longer need
  • Run triggers manually (with a confirmation dialog) before connecting to TradingView
  • View execution history in the Executed Triggers tab