TradeLock Manager API Guide
Audience: Strategy managers and integration engineers
Use case: Server-to-server strategy management and trade submission
Version: 0.9
Last updated: 2026-08-23
This guide is a production-focused API reference for TradeLock manager workflows.
TradeLock verification access is free. Strategy signals submitted through these APIs are used solely to verify and preserve intent inside TradeLock. They are not reused or shared outside TradeLock without the manager's explicit approval.
1) Base URLs
- Production:
https://tradelock.net/api - Local emulator (Hosting):
http://127.0.0.1:5003/api
All examples below use production URLs.
2) Authentication
TradeLock supports two auth methods on manager endpoints:
- API key (recommended for servers)
- Header:
X-Trader-Api-Key: <API_KEY>
- Firebase ID token
- Header:
Authorization: Bearer <FIREBASE_ID_TOKEN>
API key lifecycle endpoints
These endpoints require Firebase ID token auth (not API key auth):
POST /generate-api-keyGET /list-api-keysPOST /delete-api-keyPOST /revoke-api-key(same behavior as delete)
The manager app can also retrieve configured webhook relay details with GET /relay-access. This Firebase-ID-token-only endpoint returns a private, non-cacheable response containing the relay URL and shared relay key. Never expose that response in client-side logs, public alerts, or source code.
API key scopes
generate-api-key supports key scopes:
full(default): can access all strategiessandbox: can only submit to strategies marked as sandbox/test
A sandbox key calling a non-sandbox strategy returns:
403withcode: "SANDBOX_SCOPE_RESTRICTION"
3) Recommended Submission Modes (copy-paste first)
Use this order for manager signal ingestion:
POST /set-target-portfolio(primary)POST /logTradewithquantity+ explicit sidePOST /logTradewith single-symbolallocation_percentand no side
Default examples below are intentionally prefilled for sandbox testing:
strategy:Sandbox Strategy- API key header:
X-Trader-Api-Key: <YOUR_SANDBOX_API_KEY>
3.1 Primary: set full target portfolio
Behavior:
- Full-portfolio scope by default.
- If a current holding symbol is omitted from
targets, its target is0%.
curl -X POST "https://tradelock.net/api/set-target-portfolio" \
-H "Content-Type: application/json" \
-H "X-Trader-Api-Key: <YOUR_SANDBOX_API_KEY>" \
-d '{
"strategy": "Sandbox Strategy",
"targets": { "SPY": 33, "TLT": 33, "EEM": 10, "GSY": 15 },
"execution_anchor": "next_us_equity_open",
"open_delay_minutes": 2,
"idempotency_key": "signal-portfolio-20260308-001"
}'3.2 Quantity mode: explicit buy/sell units
curl -X POST "https://tradelock.net/api/logTrade" \
-H "Content-Type: application/json" \
-H "X-Trader-Api-Key: <YOUR_SANDBOX_API_KEY>" \
-d '{
"user_strategy_name": "Sandbox Strategy",
"asset": "AAPL:NASDAQ",
"trade_type": "buy",
"quantity": 10,
"idempotency_key": "signal-qty-buy-20260308-001"
}'3.3 Single-symbol target allocation (leave others unchanged)
curl -X POST "https://tradelock.net/api/logTrade" \
-H "Content-Type: application/json" \
-H "X-Trader-Api-Key: <YOUR_SANDBOX_API_KEY>" \
-d '{
"user_strategy_name": "Sandbox Strategy",
"asset": "AAPL:NASDAQ",
"allocation_percent": 30,
"idempotency_key": "signal-single-target-20260308-001"
}'4) Request Conventions
Strategy identity
A strategy is keyed by strategy_name in the manager workspace.
- Create is effectively an upsert on
strategy_name - Renaming an existing strategy name is not supported on update
Symbol/asset format
Trade assets are expected as uppercase symbols, with optional exchange hint:
AAPLAAPL:NASDAQBTC-USD
For equity and ETF submissions, a bare ticker is explicitly interpreted in the U.S. namespace. Qualify non-U.S. instruments with a supported exchange, such as VOD:LSE. Whitespace around the field and : separator is trimmed, but whitespace inside a symbol or exchange token is rejected.
If more than one of asset, symbol, and ticker is supplied, every value must resolve to the same canonical instrument. Conflicting values return 400 AMBIGUOUS_ASSET_INPUT; unsupported exchange hints return 400 UNSUPPORTED_EXCHANGE.
Time and timestamps
Responses may contain:
- ISO timestamps (string)
- Unix epoch milliseconds (number)
Idempotency (write safety)
Use idempotency on all write operations.
Accepted forms:
- Header:
Idempotency-Key: <key> - Body:
idempotency_key
For quick-trade, client_order_id is accepted and mapped to idempotency_key.
Validation and behavior:
- Length must be
8..200chars - Same key + same payload: replay prior response
- Same key + different payload:
409conflict - Same key while first request is processing:
409
For set-target-portfolio, same-key retries return the existing durable acceptance and rebalance_id when available.
Note for browser clients: pass idempotency in the JSON body. CORS allow-list does not include Idempotency-Key.
Fill policy and delay
For quick-trade and logTrade:
fill_policy:immediate_if_open(default) ornext_open_with_delayopen_delay_minutes: non-negative number
Delay precedence:
open_delay_minutesin request- client default delay
- global fallback (
5minutes)
Live vs CSV-import fields
For live trades (import_source omitted or live), do not send:
reported_dateuser_reported_pricereference_priceallocation_reference_price
These are only valid for import_source: "csv_import".
5) Error Model
Most errors use:
{ "error": "Human-readable message", "code": "OPTIONAL_MACHINE_CODE" }Common statuses:
200OK201Created (strategy created)202Accepted (trade queued or durable rebalance job stored)400Validation error401Authentication failed/missing403Authenticated but not allowed404Not found405Method not allowed409Idempotency conflict/in-progress500Internal error502Upstream provider failure (symbol search)
6) Endpoint Reference
6.1 API Keys
POST /generate-api-key
Generate a new manager API key.
Auth:
Authorization: Bearer <FIREBASE_ID_TOKEN>
Request body:
| Field | Type | Required | Notes |
|---|---|---|---|
key_name | string | No | Default: "My API Key" |
client_id | string | No | Default: current user UID |
key_scope | string | No | full (default) or sandbox |
Success (200):
{
"api_key": "uuid",
"key_id": "uuid",
"scope": "full",
"message": "API Key generated successfully"
}GET /list-api-keys
List API keys for authenticated user.
Auth:
Authorization: Bearer <FIREBASE_ID_TOKEN>
Success (200):
[
{
"id": "key-id",
"name": "Webhook Prod",
"created_at": "2026-02-20T15:00:00.000Z",
"last_used": "2026-02-27T10:11:12.000Z",
"status": "active",
"scope": "full"
}
]POST /delete-api-key (or POST /revoke-api-key)
Delete/revoke an API key.
Auth:
Authorization: Bearer <FIREBASE_ID_TOKEN>
Request body:
| Field | Type | Required |
|---|---|---|
api_key_id | string | Yes |
Success (200):
{ "message": "API Key deleted successfully" }GET /relay-access
Return the configured TradingView/no-code relay endpoint and shared gate key.
Auth:
Authorization: Bearer <FIREBASE_ID_TOKEN>only
Success (200):
{
"relay_endpoint": "https://tradelock-tv-relay.tradelock.workers.dev/webhook/tradingview",
"shared_relay_key": "private-value",
"label": "For TradingView, Zapier, Make, n8n, and similar webhook tools"
}The response is marked private, no-store. A missing server-side relay key returns 503.
6.2 Strategy Management
POST /ensure-sandbox-onboarding
Create or reuse the authenticated manager's sandbox strategy. This is useful for first-run integration setup and requires an API key or Firebase ID token.
Success (200) returns the sandbox strategy name and whether it was created:
{
"message": "Sandbox onboarding is ready.",
"sandbox": {
"strategy_name": "Sandbox Strategy",
"strategy_created": true,
"key_created": false,
"sandbox_api_key": null,
"sandbox_api_key_preview": null
}
}POST /reset-sandbox
Delete trades, daily snapshots, and pending trades belonging to the authenticated manager's sandbox strategy, then reset its verification state. This is destructive and requires an API key or Firebase ID token. It returns 404 when no sandbox strategy exists.
GET /client-config
Read the effective manager client settings used by delayed execution and allocation rebalances.
Auth:
- API key or Firebase ID token
Optional query parameter: client_id. When omitted, the authenticated client identity is used.
Success (200):
{
"client_id": "manager-client-id",
"default_open_delay_minutes": 2,
"effective_default_open_delay_minutes": 2,
"min_rebalance_notional_usd": 25,
"effective_min_rebalance_notional_usd": 25,
"source": "client",
"exists": true
}POST|PUT|PATCH /client-config/update
Update one or both client settings. The body must include at least one of default_open_delay_minutes or min_rebalance_notional_usd; both values must be non-negative numbers. Auth is API key or Firebase ID token.
Optional client_id may be supplied in the body or query string. Success (200) returns the updated values.
GET /strategies
List strategies for authenticated manager.
Auth:
- API key or ID token
Query params:
| Param | Type | Required | Notes |
|---|---|---|---|
limit | number | No | 1..100, default 50 |
page_token | string | No | Last returned strategy ID |
include_archived | boolean-like | No | true/1/yes to include soft-deleted |
Success (200):
{
"strategies": [
{
"id": "Momentum Core",
"strategy_name": "Momentum Core",
"access_mode": "workspace",
"hub_status": "not_requested",
"tags": ["momentum"],
"asset_types": ["equity"],
"initial_capital_usd": 100000
}
],
"next_page_token": null
}Notes:
- When OpenTimestamps verification anchors are enabled and the current account is eligible to see them, strategies may also include
verification_anchor_latest_v1. verification_anchor_latest_v1is the latest per-strategy anchor summary and includes:provider:opentimestampssnapshot_datestatus:pending,attested, orerroranchor_pathandproof_pathanchor_sha256stamped_at,upgraded_at,attested_at,last_error
Example:
{
"verification_anchor_latest_v1": {
"provider": "opentimestamps",
"snapshot_date": "2026-04-04",
"status": "pending",
"anchor_sha256": "f8f8...",
"anchor_path": "verification/ots/.../anchor.json",
"proof_path": "verification/ots/.../anchor.json.ots"
}
}GET /verification-anchor-file
Download the latest OpenTimestamps anchor artifact for one of your strategies.
Auth:
- ID token
Query params:
| Param | Type | Required | Notes |
|---|---|---|---|
strategyName or strategy_name | string | Yes | Target strategy |
kind | string | Yes | anchor or proof |
Behavior:
kind=anchorreturns the latestanchor.json.kind=proofreturns the latest detachedanchor.json.otsproof.- Returns
404when the strategy has no anchor yet, the feature is disabled, or the current account is not eligible to view anchor files.
Success:
200with an attachment response- Content type is
application/jsonforanchor - Content type is
application/octet-streamforproof
POST /createStrategy
Create or update a strategy by strategy_name.
Auth:
- API key or ID token
Request body:
| Field | Type | Required | Notes |
|---|---|---|---|
strategy_name | string | Yes | Strategy ID in workspace |
description | string | No | |
public_summary | string | No | Defaults to description if missing |
access_mode | string | No | workspace, shareable, or invite_only; default workspace |
hub_status | string | No | Providers may use not_requested or under_review; listed is admin-managed |
public_slug | string | No | Applied when access_mode=shareable |
tags | string[] | No | Up to 25 entries after normalization |
asset_types | string[] | No | Up to 25 entries after normalization |
metadata | object | No | Primitive/object values only |
initial_capital_usd | number | No | Must be positive if provided |
trade_hide_days | number | No | Days of recent trades hidden from public viewers. Allowed: 0 (show all), 30, 60, 90, 9999 (hide all). Default: 0 |
min_rebalance_move_pct | number | No | Drift filter for set-target-portfolio. Legs with a notional move below this % of running capital are skipped as no-ops. Range 0–100. Default: 1 |
Success:
201when created200when existing strategy is updated
{
"message": "Strategy created successfully",
"created": true,
"strategy": {
"id": "Momentum Core",
"strategy_name": "Momentum Core",
"is_deleted": false
}
}POST|PUT|PATCH /update-strategy (alias: /updateStrategy)
Patch strategy fields.
Auth:
- API key or ID token
Request body:
| Field | Type | Required | Notes |
|---|---|---|---|
strategy_id or strategy_name | string | Yes | Target strategy |
description | string | No | |
public_summary | string | No | |
access_mode | string | No | workspace, shareable, or invite_only |
hub_status | string | No | not_requested or under_review; listed is admin-managed |
public_slug | string | No | Regenerated/sanitized when needed |
tags | string[] | No | |
asset_types | string[] | No | |
metadata | object | No | |
is_deleted | boolean | No | Soft-delete toggle |
initial_capital_usd | number | No | Must be positive |
trade_hide_days | number | No | Days of recent trades hidden from public viewers. Allowed: 0, 30, 60, 90, 9999. |
min_rebalance_move_pct | number | No | Drift filter threshold 0–100. |
Constraints:
- Renaming strategy name is not supported (
400) verification_rateis server-managed and cannot be set
Success (200):
{
"message": "Strategy updated successfully",
"strategy": {
"id": "Momentum Core",
"strategy_name": "Momentum Core"
}
}POST|DELETE /delete-strategy (alias: /deleteStrategy)
Soft-delete (archive) a strategy. Archiving also cancels active pending trades for the same strategy before the archive is applied. Archived strategies are preserved indefinitely and can be restored or permanently deleted from the owner's account.
Auth:
- API key or ID token
Request body:
| Field | Type | Required |
|---|---|---|
strategy_id or strategy_name | string | Yes |
Success (200):
{
"message": "Strategy archived successfully",
"strategy_id": "Momentum Core",
"deleted": true,
"pending_trade_cancellation": {
"matched_pending_trades": 1,
"cancelled_count": 1,
"already_cancelled_count": 0,
"processing_count": 0,
"not_cancellable_count": 0,
"failed_count": 0
}
}Conflict (409):
- Returned as
ARCHIVE_BLOCKED_BY_PENDING_TRADESif one or more matching pending trades are already processing or could not be cancelled safely.
POST|DELETE /permanent-delete-strategy (alias: /permanentDeleteStrategy)
Permanently delete an archived strategy and its strategy-owned data. This removes the strategy document tree, matching pending trades, immutable trade storage files, verification snapshot files, and OpenTimestamps anchor/proof files tied to that strategy.
Auth:
- ID token only
Request body:
| Field | Type | Required |
|---|---|---|
strategy_id or strategy_name | string | Yes |
confirmation_text | string | Yes; must exactly equal the strategy ID |
target_user_id | string | Admin only; omit when deleting your own strategy |
Success (200):
{
"message": "Strategy permanently deleted",
"strategy_id": "Momentum Core",
"deleted": true,
"permanent": true
}Conflict (409):
- Returned as
STRATEGY_NOT_ARCHIVEDif the strategy has not been archived first.
API-key authentication is rejected for permanent deletion. Retrying a completed deletion returns success with already_deleted: true.
GET /strategy-audit-pack
Download a portable strategy audit ZIP that can be verified without TradeLock, Firestore, credentials, npm, or network access.
Auth:
- ID token or full-access API key
Query parameters:
| Field | Type | Required |
|---|---|---|
strategyName or strategy_id | string | Yes |
Success (200) returns application/zip. Extract the archive and run node verify.cjs . with Node.js 18 or newer.
6.3 Trade Validation and Submission
POST /validate-trade (alias: POST /dry-run-trade)
Validate and normalize a trade request without creating a trade.
Auth:
- API key or ID token
Key inputs:
- Strategy:
strategyorstrategy_nameoruser_strategy_name(optional if user has exactly one strategy) - Asset:
tickerorsymbolorasset - Side:
trade_typeorsideoraction(buy|sell) - Size: exactly one of
quantityor allocation aliases
Allocation aliases:
allocation_percentallocation_pctallocationPercentageallocation%
Success (200):
{
"valid": true,
"mode": "validate_only",
"key_scope": "full",
"normalized_payload": {
"user_strategy_name": "Momentum Core",
"asset": "AAPL",
"trade_type": "buy",
"allocation_percent": 10,
"fill_policy": "immediate_if_open"
},
"notes": [
"Allocation mode with trade_type sizes this order from strategy running capital."
]
}POST /quick-trade
Manager-friendly trade submission with broad aliases.
Recommendation:
- Keep this for backwards compatibility or low-code adapters.
- For manager-driven portfolio instructions, prefer
POST /set-target-portfolio.
Auth:
- API key or ID token
Request fields:
| Canonical field | Accepted input keys | Required | Notes |
|---|---|---|---|
| strategy | strategy, strategy_name, user_strategy_name | Conditionally | Optional only if exactly one strategy exists |
| asset | ticker, symbol, asset | Yes | SYMBOL or SYMBOL:EXCHANGE |
| trade side | trade_type, side, action | Depends | Required when using quantity |
| quantity | quantity, qty | Depends | Mutually exclusive with allocation |
| allocation | allocation_percent, allocation_pct, allocationPercentage, allocation% | Depends | Mutually exclusive with quantity |
| idempotency | idempotency_key, client_order_id | Recommended | Use in production |
| execution | fill_policy, open_delay_minutes | No | |
| tags | tags | No | string[] |
Behavior:
- Calls
logTradeinternally after normalization - Returns immediate fill (
200) or queued (202) - Pending replacement rules for same
strategy + asset: target_allocationmode (sendallocation_percentand omit side) replaces the existing active pending target-allocation intent for that symbol.quantitymode and side-basedallocation_percentmode append as separate pending orders (FIFO).
POST /set-target-portfolio
Asynchronous contract:
idempotency_key(orclient_order_id) is required. The endpoint returns202 Acceptedwith a durablerebalance_id; pollGET /rebalance-status?rebalance_id=...forcompleted,partially_completed, orfailed. A timeout is an unknown outcome—retry the identical payload with the same key. Only one rebalance may be active per strategy.
Set an authoritative target portfolio for a strategy.
- Full-portfolio semantics are default: symbols with open positions that are not in
targetsare auto-targeted to0%. - Before submitting new legs, the endpoint cancels all cancellable pending trades for the same strategy by default.
- Trade legs are submitted sequentially (sells first, then buys).
- Each leg is submitted as target-allocation logic (
allocation_percentwithout side). - Targets do not need to sum to
100. Totals below100leave residual cash uninvested. For example, an80total target is valid and leaves20%in cash. - Legs whose notional move is smaller than
min_rebalance_move_pct(set on the strategy, default1%) are silently skipped. The response marks them withdrift_filtered: trueanddrift_pct.
Pricing and sizing behavior:
set-target-portfoliosizing uses last-price lookup (getLastPrice) for each leg, not Alpaca execution quotes.- Provider order for last-price lookup:
- Crypto-like symbols:
coinbase->twelve-data->yahoo-finance2->alpha-vantage - Futures-like symbols:
twelve-data->yahoo-finance2->alpha-vantage->coinbase - Other symbols: configured default provider first, then remaining providers.
- Configured default provider:
twelve-datawhenTWELVEDATA_API_KEYorTWELVE_DATA_API_KEYis present- else
alpha-vantagewhenALPHA_VANTAGE_API_KEYis present - else
yahoo-finance2 - If no provider returns a usable quote, the endpoint returns
400with a sizing error per symbol.
Auth:
- API key or ID token
Request fields:
| Field | Type | Required | Notes |
|---|---|---|---|
strategy / strategy_name / user_strategy_name | string | Conditionally | Optional only if exactly one strategy exists |
targets | array or object map | Yes | Array: [{ "symbol": "SPY", "allocation_percent": 33 }] or map: { "SPY": 33 } |
execution_anchor | enum | No | now (default) or next_us_equity_open |
execute_on_stock_open | boolean | No | Alias for execution_anchor=next_us_equity_open |
open_delay_minutes | number | No | Applied per leg |
cancel_pending_trades_first | boolean | No | Default true; set false to preserve the current pending queue |
dry_run | boolean | No | If true, returns plan only (no submissions) |
idempotency_key / client_order_id | string | Yes | Required; timeout retries must reuse the identical payload and key |
tags | string[] | No | Applied to each submitted leg |
Example:
{
"strategy": "Sandbox Strategy",
"targets": {
"SPY": 33,
"TLT": 33,
"EEM": 10,
"GSY": 15
},
"execution_anchor": "next_us_equity_open",
"open_delay_minutes": 2,
"idempotency_key": "stp-20260308-001"
}Acceptance (202) returns after the durable job is created:
{
"message": "Rebalance accepted for asynchronous processing.",
"rebalance_id": "stp_1773763355292_ganlirnm",
"strategy": "Sandbox Strategy",
"status": "accepted",
"status_url": "/api/rebalance-status?rebalance_id=stp_1773763355292_ganlirnm"
}- Same key and identical payload returns the same
rebalance_id. - Same key with a different payload returns
409 IDEMPOTENCY_PAYLOAD_CONFLICT. - Only one rebalance can be active per strategy. Another returns
409 REBALANCE_ALREADY_ACTIVEwithactive_rebalance_id. - Pricing, sizing, pending-trade cancellation, and leg submission happen in the durable worker.
- A timeout is an unknown outcome. Retry the identical payload and key; do not submit a replacement rebalance.
GET /rebalance-status
Get the durable state and result of an accepted portfolio rebalance.
Auth: API key or ID token. The rebalance must belong to the authenticated trader.
| Param | Required | Notes |
|---|---|---|
rebalance_id / rebalanceId | Yes | ID returned by set-target-portfolio |
States:
accepted: durable job storedplanning: worker is pricing, sizing, or submitting legscompleted: all required legs were submitted or no trades were neededpartially_completed: at least one leg succeeded before a later failurefailed: job did not complete successfully
Terminal responses include result with the summary, planned and processed legs, trade or pending-trade IDs, and error details.
Client flow:
- Persist the payload and idempotency key before submission.
- On
202, persistrebalance_id. - Poll until
completed,partially_completed, orfailed. - If the connection is lost before
202, retry the identical submission with the same key.
- When
cancel_pending_trades_firstis enabled, responses also includepreflight_pending_trade_reset. - If a pending trade is already
processing, or cancellation fails during preflight, the job reachesfailedbefore submitting new legs.
Example response fragment:
{
"rebalance_id": "stp_1773763355292_ganlirnm",
"strategy": "Sandbox Strategy",
"status": "completed",
"result": {
"message": "Target portfolio submitted successfully.",
"summary": {
"immediate_count": 0,
"queued_count": 4,
"no_op_count": 0
}
}
}POST /logTrade
Advanced trade endpoint.
Auth:
- API key or ID token
Core fields:
| Field | Type | Required | Notes |
|---|---|---|---|
user_strategy_name / strategy_name / strategy | string | Conditionally | Optional only if exactly one strategy exists |
asset | string | Yes | SYMBOL or SYMBOL:EXCHANGE |
trade_type / side / action | buy|sell | Depends | Required for direct quantity mode |
quantity / qty | number | Depends | Required unless allocation is provided |
allocation_percent and aliases | number | Depends | Required unless quantity is provided |
fill_policy | enum | No | immediate_if_open (default) or next_open_with_delay |
open_delay_minutes | number | No | non-negative |
idempotency_key | string | Recommended | or Idempotency-Key header |
tags | string[] | No |
Sizing modes:
- Quantity mode
- send
quantity+ explicit side
- Allocation-percent mode
- send
allocation_percent+ side - quantity is computed from strategy running capital
- Target-allocation mode
- send
allocation_percentand omit side - endpoint computes target position delta and direction
- queued submissions in this mode replace prior active pending target-allocation intent for the same strategy+asset
CSV import-only fields (import_source: "csv_import"):
| Field | Type | Notes |
|---|---|---|
import_source | string | Must equal csv_import |
reported_date | ISO-8601 string | Optional |
user_reported_price | number | Required and must be > 0 |
reference_price | number | Optional (sizing reference) |
allocation_reference_price | number | Optional (sizing reference) |
Optional enrichment fields:
rankable_strategy_id,isin,tick_size,multiplier,point_value,margin,commission
Live execution quote behavior:
logTradeuses execution quote lookup (getExecutionQuote) when processing non-CSV trades.- For non-crypto and non-futures symbols, execution quotes try enabled providers in
EXECUTION_QUOTE_PROVIDER_ORDERpriority (defaultalpaca,tradier). - Alpaca remains opt-in through
ALPACA_EQUITY_ENABLED; Tradier is independently opt-in throughTRADIER_EQUITY_ENABLED. Merely configuringTRADIER_ACCESS_TOKENdoes not activate it. - Alpaca and Tradier quotes use top-of-book side pricing: buy -> ask, sell -> bid. Stale/crossed/missing side quotes are rejected. Tradier responses are also checked for matching symbols and stock/ETF instrument types.
- If an execution-quote provider fails, the next enabled provider is tried. If all fail, execution falls back to last-price providers.
- Fallback executions are marked with
execution_basis: "last"and includequote_fallback_reason. - If no quote is available (or market is not open), the trade is queued (
202) for delayed processing; failed delayed attempts can move toerror_processing.
Example provider configuration:
ALPACA_EQUITY_ENABLED=true
TRADIER_EQUITY_ENABLED=true
TRADIER_ACCESS_TOKEN=your-production-token
EXECUTION_QUOTE_PROVIDER_ORDER=tradier,alpacaTradier uses the production consolidated feed. TRADIER_API_KEY is accepted as an alias for TRADIER_ACCESS_TOKEN. Its sandbox feed is delayed and is not used by this integration.
Success patterns:
Immediate/logged (200):
{
"message": "Trade logged successfully!",
"tradeId": "abc123",
"execution": {
"fill_policy": "immediate_if_open",
"resolved_open_delay_minutes": 5
},
"sizing": {
"mode": "allocation_percent",
"allocation_percent": 10,
"quantity": 42
},
"hybrid": {
"verified": true,
"storageRef": "strategies/.../snapshot.json",
"hash": "..."
},
"price_data": {
"price": 201.12,
"market_state": "REGULAR"
}
}Queued (202):
{
"message": "Trade received and queued for processing when market opens.",
"pendingTradeId": "pnd_456",
"current_market_state": "CLOSED",
"execution": {
"fill_policy": "next_open_with_delay",
"waiting_for_next_market_session": false,
"resolved_open_delay_minutes": 5
}
}No-op target allocation (200):
{
"message": "No trade created. Strategy is already at the requested target allocation.",
"no_op": true
}6.4 Trade Status and History
GET /trade-status
Get lifecycle/timeline for a trade or pending trade.
Auth:
- API key or ID token
Query params:
| Param | Required | Notes |
|---|---|---|
strategyName or strategy_name | Yes | Strategy name |
tradeId or trade_id | Yes | tradeId or pendingTradeId from submit response |
Success (200) returns timeline-style response with:
source:pending_tradesorstrategy_tradecurrent_status: e.g.queued,pending_delay,filled,immutable_stored,verified,error_*snapshot_freshness:not_ready,fresh,stale,unknownexecution,filled,timeline
GET /strategy-trades
Get strategy trade history (and optionally pending queue).
Auth:
- API key or ID token
Query params:
| Param | Required | Notes |
|---|---|---|
strategy_name | Yes | Strategy name |
limit | No | Default 100 |
include_pending | No | true/1/yes to include active pending trades |
Success (200):
- Without pending:
{ "trades": [...] } - With pending:
{ "trades": [...], "pending_trades": [...] }
POST /cancel-pending-trade
Cancel one queued pending trade before execution.
Auth:
- API key or ID token
Request body:
| Field | Type | Required | Notes |
|---|---|---|---|
strategy_name | string | Yes | Strategy name |
pending_trade_id | string | Yes | ID from queued trade response |
reason | string | No | Optional cancellation note |
Success (200):
{
"message": "Pending trade cancelled successfully.",
"pending_trade_id": "pnd_456",
"strategy_name": "Sandbox Strategy",
"status": "cancelled"
}Possible conflicts:
409if order is alreadyprocessingor in another non-cancellable status404if pending trade does not belong to caller/strategy
POST /cancel-all-pending-trades
Cancel all cancellable pending trades for one strategy.set-target-portfolio now performs this queue reset automatically by default, so use this endpoint when you want to clear the queue explicitly without submitting a new target portfolio.
Auth:
- API key or ID token
Request body:
| Field | Type | Required | Notes |
|---|---|---|---|
strategy_name | string | Yes | Strategy name to clear |
reason | string | No | Optional cancellation note applied to all cancelled rows |
Success (200):
{
"message": "Cancelled 3 pending trade(s) for strategy 'Sandbox Strategy'.",
"strategy_name": "Sandbox Strategy",
"matched_pending_trades": 5,
"cancelled_count": 3,
"already_cancelled_count": 1,
"processing_count": 1,
"not_cancellable_count": 0,
"failed_count": 0
}6.5 Market Data Utilities
GET|POST /symbol-search
Lookup symbols across providers.
Auth:
- Required
- Send either:
X-Trader-Api-Key: <API_KEY>Authorization: Bearer <FIREBASE_ID_TOKEN>
Inputs:
| Field | Type | Required | Notes |
|---|---|---|---|
q | string | Yes | query text |
provider | string | No | yahoo-finance2, alpha-vantage, twelve-data, coinbase |
limit | number | No | default 10, max 25 |
Success (200):
{
"query": "AAPL",
"count": 1,
"provider_used": "twelve-data",
"attempts": [
{ "provider": "twelve-data", "status": "success" }
],
"results": [
{
"symbol": "AAPL",
"name": "Apple Inc",
"exchange": "NASDAQ",
"type": "Common Stock",
"provider": "twelve-data"
}
]
}If all providers fail: 502 with provider attempt details.
GET|POST /fetch-price (alias: /fetchPrice)
Get last/current price and market state.
Auth:
- Required
- Send either:
X-Trader-Api-Key: <API_KEY>Authorization: Bearer <FIREBASE_ID_TOKEN>
Inputs:
| Field | Type | Required | Notes |
|---|---|---|---|
symbol | string | Yes | e.g. AAPL |
provider | string | No | provider hint |
When market is closed, endpoint can still return 200 with last available price and note.
Provider routing notes:
- Crypto symbol normalization for Coinbase:
BTC/USDis normalized toBTC-USD- bare symbols like
BTCare normalized toBTC-USD - Crypto symbols are routed to Coinbase first, then fallback providers.
7) cURL Quickstart
1. Set portfolio targets (primary)
curl -X POST "https://tradelock.net/api/set-target-portfolio" \
-H "Content-Type: application/json" \
-H "X-Trader-Api-Key: <YOUR_SANDBOX_API_KEY>" \
-d '{
"strategy": "Sandbox Strategy",
"targets": {
"SPY": 33,
"TLT": 33,
"EEM": 10,
"GSY": 15
},
"execution_anchor": "next_us_equity_open",
"open_delay_minutes": 2,
"idempotency_key": "signal-portfolio-20260308-001"
}'2. Buy by quantity
curl -X POST "https://tradelock.net/api/logTrade" \
-H "Content-Type: application/json" \
-H "X-Trader-Api-Key: <YOUR_SANDBOX_API_KEY>" \
-d '{
"user_strategy_name": "Sandbox Strategy",
"asset": "AAPL:NASDAQ",
"trade_type": "buy",
"quantity": 10,
"idempotency_key": "signal-qty-buy-20260308-001"
}'3. Individual target allocation (single symbol)
curl -X POST "https://tradelock.net/api/logTrade" \
-H "Content-Type: application/json" \
-H "X-Trader-Api-Key: <YOUR_SANDBOX_API_KEY>" \
-d '{
"user_strategy_name": "Sandbox Strategy",
"asset": "AAPL:NASDAQ",
"allocation_percent": 30,
"idempotency_key": "signal-single-target-20260308-001"
}'4. Poll status
curl "https://tradelock.net/api/trade-status?strategyName=Sandbox%20Strategy&tradeId=<TRADE_OR_PENDING_ID>" \
-H "X-Trader-Api-Key: <YOUR_SANDBOX_API_KEY>"8) Integration Checklist
- Use one API key per integration (webhook, backend service, ETL).
- Always send
idempotency_keyon write requests. - Use
validate-tradebefore enabling production automation. - Alert on repeated
4xxresponses. - Poll
trade-statusfor queued trades. - Poll
rebalance-statusfor accepted portfolio submissions. - Separate sandbox and production strategies/keys.
9) Changelog
- 0.8 (2026-08-16)
- Documented the authenticated webhook relay access endpoint.
- Documented sandbox onboarding and sandbox reset endpoints.
- Documented client execution configuration read/update endpoints.
- Clarified exchange qualification and conflicting asset-field behavior.
- 0.7 (2026-07-13)
- Documented durable asynchronous portfolio jobs and required idempotency.
- Added
GET /rebalance-status, terminal states, polling, and timeout recovery.
- 0.6 (2026-04-22)
- Added
trade_hide_daysfield tocreateStrategyandupdate-strategy. Controls how many days of recent trades are hidden from public viewers (0,30,60,90,9999). - Added
min_rebalance_move_pctfield tocreateStrategyandupdate-strategy. Legs inset-target-portfoliowhose notional move is below this % of running capital are skipped. Default1. - Documented drift filter response fields (
drift_filtered,drift_pct) inset-target-portfolio.
- 0.5 (2026-03-17)
- Documented
set-target-portfoliopreflight cancellation of existing pending trades. - Documented
cancel_pending_trades_first=falseopt-out andpreflight_pending_trade_resetresponse field. - Clarified request-level replay behavior for
set-target-portfolioidempotency retries.
- 0.4 (2026-03-08)
- Added
POST /cancel-all-pending-tradesfor strategy-scoped queue reset. - Documented bulk-cancel response counters (
cancelled_count,processing_count, etc.).
- 0.3 (2026-03-08)
- Added clear recommended submission order with
set-target-portfolioas primary. - Added copy-paste sandbox defaults (
Sandbox Strategy,<YOUR_SANDBOX_API_KEY>). - Clarified three manager submission modes: full portfolio targets, quantity buy/sell, and single-symbol target allocation.
- 0.2 (2026-02-27)
- Rewrote guide into endpoint-reference format.
- Corrected strategy endpoint requirements and status codes.
- Corrected auth requirements for utility endpoints.
- Added API key lifecycle endpoints and sandbox scope behavior.
- Clarified sizing modes, idempotency behavior, and queue semantics.
- 0.1 (2026-02-27)
- Initial manager-focused API guide.