{
"secret": "YOUR_WEBHOOK_SECRET",
"action": "flatten_and_lock",
"id": "pine-lock-{{timenow}}"
}Target Lock and script close requests.
What Target Lock does when profit reaches your level, and how to send a close or flatten-and-lock request from a TradingView Pine alert or a Python script.
What Target Lock does
When profit on a connected account reaches your profit level plus your buffer, Target Lock cancels working orders, closes open positions, reads the positions back to confirm the account is flat, and locks execution. It covers challenge, funded sim and funded live accounts. Funded live accounts are coming soon: until then Target Lock locks execution and sends an alert, and does not send closing orders to them.
The always-on watcher measures profit from the balance and open profit and loss the broker streams, against a starting balance saved for the account. It does not wait for an order or for you to save settings. Keep-flat is optional: when it is on, a new position opened on a locked account is closed again.
Target Lock places closing orders only where the firm allows orders from FirmGated's servers (see Connect Brokers). Where a firm does not, or has not confirmed it, Target Lock sends an alert with the account's status and leaves positions and orders as they are. Every result is one of: armed, triggered, flattening, locked, or needs attention. A needs-attention alert lists what is still open at the broker.
Send a close request from a script
Post JSON to your strategy's webhook URL, the same URL your signals use. The request is accepted with HTTP 202 and runs in the background; the result arrives as a Target Lock alert and in your audit log. A request works while execution is locked. The sim-only plan rule and each firm's automation route apply to script requests exactly as they do to signals.
| Field | Type | Example | What it does |
|---|---|---|---|
secret | string | "YOUR_WEBHOOK_SECRET" | Your strategy's webhook secret, the same one your signals use. Keep it out of shared scripts. |
action | string | "close_all" | "flatten_and_lock" | close_all cancels working orders and closes positions; execution stays on. flatten_and_lock does the same and then locks execution with Target Lock. |
account | string | "YOUR_BROKER_ACCOUNT_ID" | Optional. Limits the request to one connected account on this strategy. Without it, every connected account on the strategy is included. |
id | string | "pine-lock-1760000000000" | Optional, up to 120 characters. A request id that was already handled runs once. |
Copy-paste snippets
Replace the YOUR_ placeholders with your own values. In TradingView, create the alert with the Pine script as its condition, choose Any alert() function call, and set the webhook URL to your strategy's URL. Check the Pine example in the Pine Editor against your own script before relying on it.
{
"secret": "YOUR_WEBHOOK_SECRET",
"action": "close_all",
"id": "pine-close-{{timenow}}"
}{
"secret": "YOUR_WEBHOOK_SECRET",
"action": "flatten_and_lock",
"account": "YOUR_BROKER_ACCOUNT_ID",
"id": "pine-lock-{{timenow}}"
}//@version=6
strategy("Target Lock request", overlay=true)
profitLevel = input.float(1500.0, "Profit level in account currency")
// strategy.netprofit is this script's own closed-trade profit; any value your script tracks works here.
if barstate.isconfirmed and strategy.netprofit >= profitLevel
alert('{"secret":"YOUR_WEBHOOK_SECRET","action":"flatten_and_lock","id":"pine-lock-' + str.tostring(time) + '"}', alert.freq_once_per_bar_close)import os
import time
import requests
WEBHOOK_URL = "https://firmgated.com/api/webhooks/YOUR_STRATEGY_SLUG"
# Keep the secret outside the script: export FIRMGATED_WEBHOOK_SECRET=...
SECRET = os.environ["FIRMGATED_WEBHOOK_SECRET"]
def request_close(action="flatten_and_lock", account=None):
"""action: "close_all" or "flatten_and_lock". account: optional broker account id."""
body = {
"secret": SECRET,
"action": action,
# A stable id makes a retried request run once.
"id": f"py-{action}-{int(time.time())}",
}
if account:
body["account"] = account
response = requests.post(WEBHOOK_URL, json=body, timeout=10)
response.raise_for_status()
return response.json() # {"ok": True, "accepted": True, "action": "...", "accounts": 1}
if __name__ == "__main__":
print(request_close())curl -X POST "https://firmgated.com/api/webhooks/YOUR_STRATEGY_SLUG" \
-H "Content-Type: application/json" \
-d '{"secret":"'"$FIRMGATED_WEBHOOK_SECRET"'","action":"close_all","id":"curl-close-1"}'