Docs

Manager API Reference

Detailed endpoint reference for strategies, trade submission, status, and utility APIs.

Managerv0.9Updated Aug 23, 2026

Need the source file for an AI workflow or offline reference? The raw markdown remains available at /docs/TRADELOCK_MANAGER_API_REFERENCE.md.

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:

  1. API key (recommended for servers)
  • Header: X-Trader-Api-Key: <API_KEY>
  1. 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-key
  • GET /list-api-keys
  • POST /delete-api-key
  • POST /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 strategies
  • sandbox: can only submit to strategies marked as sandbox/test

A sandbox key calling a non-sandbox strategy returns:

  • 403 with code: "SANDBOX_SCOPE_RESTRICTION"

Use this order for manager signal ingestion:

  1. POST /set-target-portfolio (primary)
  2. POST /logTrade with quantity + explicit side
  3. POST /logTrade with single-symbol allocation_percent and 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 is 0%.
bash
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

bash
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)

bash
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:

  • AAPL
  • AAPL:NASDAQ
  • BTC-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..200 chars
  • Same key + same payload: replay prior response
  • Same key + different payload: 409 conflict
  • 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) or next_open_with_delay
  • open_delay_minutes: non-negative number

Delay precedence:

  1. open_delay_minutes in request
  2. client default delay
  3. global fallback (5 minutes)

Live vs CSV-import fields

For live trades (import_source omitted or live), do not send:

  • reported_date
  • user_reported_price
  • reference_price
  • allocation_reference_price

These are only valid for import_source: "csv_import".

5) Error Model

Most errors use:

json
{ "error": "Human-readable message", "code": "OPTIONAL_MACHINE_CODE" }

Common statuses:

  • 200 OK
  • 201 Created (strategy created)
  • 202 Accepted (trade queued or durable rebalance job stored)
  • 400 Validation error
  • 401 Authentication failed/missing
  • 403 Authenticated but not allowed
  • 404 Not found
  • 405 Method not allowed
  • 409 Idempotency conflict/in-progress
  • 500 Internal error
  • 502 Upstream 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:

FieldTypeRequiredNotes
key_namestringNoDefault: "My API Key"
client_idstringNoDefault: current user UID
key_scopestringNofull (default) or sandbox

Success (200):

json
{
  "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):

json
[
  {
    "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:

FieldTypeRequired
api_key_idstringYes

Success (200):

json
{ "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):

json
{
  "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:

json
{
  "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):

json
{
  "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:

ParamTypeRequiredNotes
limitnumberNo1..100, default 50
page_tokenstringNoLast returned strategy ID
include_archivedboolean-likeNotrue/1/yes to include soft-deleted

Success (200):

json
{
  "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_v1 is the latest per-strategy anchor summary and includes:
  • provider: opentimestamps
  • snapshot_date
  • status: pending, attested, or error
  • anchor_path and proof_path
  • anchor_sha256
  • stamped_at, upgraded_at, attested_at, last_error

Example:

json
{
  "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:

ParamTypeRequiredNotes
strategyName or strategy_namestringYesTarget strategy
kindstringYesanchor or proof

Behavior:

  • kind=anchor returns the latest anchor.json.
  • kind=proof returns the latest detached anchor.json.ots proof.
  • Returns 404 when the strategy has no anchor yet, the feature is disabled, or the current account is not eligible to view anchor files.

Success:

  • 200 with an attachment response
  • Content type is application/json for anchor
  • Content type is application/octet-stream for proof

POST /createStrategy

Create or update a strategy by strategy_name.

Auth:

  • API key or ID token

Request body:

FieldTypeRequiredNotes
strategy_namestringYesStrategy ID in workspace
descriptionstringNo
public_summarystringNoDefaults to description if missing
access_modestringNoworkspace, shareable, or invite_only; default workspace
hub_statusstringNoProviders may use not_requested or under_review; listed is admin-managed
public_slugstringNoApplied when access_mode=shareable
tagsstring[]NoUp to 25 entries after normalization
asset_typesstring[]NoUp to 25 entries after normalization
metadataobjectNoPrimitive/object values only
initial_capital_usdnumberNoMust be positive if provided
trade_hide_daysnumberNoDays of recent trades hidden from public viewers. Allowed: 0 (show all), 30, 60, 90, 9999 (hide all). Default: 0
min_rebalance_move_pctnumberNoDrift filter for set-target-portfolio. Legs with a notional move below this % of running capital are skipped as no-ops. Range 0100. Default: 1

Success:

  • 201 when created
  • 200 when existing strategy is updated
json
{
  "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:

FieldTypeRequiredNotes
strategy_id or strategy_namestringYesTarget strategy
descriptionstringNo
public_summarystringNo
access_modestringNoworkspace, shareable, or invite_only
hub_statusstringNonot_requested or under_review; listed is admin-managed
public_slugstringNoRegenerated/sanitized when needed
tagsstring[]No
asset_typesstring[]No
metadataobjectNo
is_deletedbooleanNoSoft-delete toggle
initial_capital_usdnumberNoMust be positive
trade_hide_daysnumberNoDays of recent trades hidden from public viewers. Allowed: 0, 30, 60, 90, 9999.
min_rebalance_move_pctnumberNoDrift filter threshold 0100.

Constraints:

  • Renaming strategy name is not supported (400)
  • verification_rate is server-managed and cannot be set

Success (200):

json
{
  "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:

FieldTypeRequired
strategy_id or strategy_namestringYes

Success (200):

json
{
  "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_TRADES if 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:

FieldTypeRequired
strategy_id or strategy_namestringYes
confirmation_textstringYes; must exactly equal the strategy ID
target_user_idstringAdmin only; omit when deleting your own strategy

Success (200):

json
{
  "message": "Strategy permanently deleted",
  "strategy_id": "Momentum Core",
  "deleted": true,
  "permanent": true
}

Conflict (409):

  • Returned as STRATEGY_NOT_ARCHIVED if 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:

FieldTypeRequired
strategyName or strategy_idstringYes

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: strategy or strategy_name or user_strategy_name (optional if user has exactly one strategy)
  • Asset: ticker or symbol or asset
  • Side: trade_type or side or action (buy|sell)
  • Size: exactly one of quantity or allocation aliases

Allocation aliases:

  • allocation_percent
  • allocation_pct
  • allocationPercentage
  • allocation%

Success (200):

json
{
  "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 fieldAccepted input keysRequiredNotes
strategystrategy, strategy_name, user_strategy_nameConditionallyOptional only if exactly one strategy exists
assetticker, symbol, assetYesSYMBOL or SYMBOL:EXCHANGE
trade sidetrade_type, side, actionDependsRequired when using quantity
quantityquantity, qtyDependsMutually exclusive with allocation
allocationallocation_percent, allocation_pct, allocationPercentage, allocation%DependsMutually exclusive with quantity
idempotencyidempotency_key, client_order_idRecommendedUse in production
executionfill_policy, open_delay_minutesNo
tagstagsNostring[]

Behavior:

  • Calls logTrade internally after normalization
  • Returns immediate fill (200) or queued (202)
  • Pending replacement rules for same strategy + asset:
  • target_allocation mode (send allocation_percent and omit side) replaces the existing active pending target-allocation intent for that symbol.
  • quantity mode and side-based allocation_percent mode append as separate pending orders (FIFO).

POST /set-target-portfolio

Asynchronous contract: idempotency_key (or client_order_id) is required. The endpoint returns 202 Accepted with a durable rebalance_id; poll GET /rebalance-status?rebalance_id=... for completed, partially_completed, or failed. 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 targets are auto-targeted to 0%.
  • 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_percent without side).
  • Targets do not need to sum to 100. Totals below 100 leave residual cash uninvested. For example, an 80 total target is valid and leaves 20% in cash.
  • Legs whose notional move is smaller than min_rebalance_move_pct (set on the strategy, default 1%) are silently skipped. The response marks them with drift_filtered: true and drift_pct.

Pricing and sizing behavior:

  • set-target-portfolio sizing 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-data when TWELVEDATA_API_KEY or TWELVE_DATA_API_KEY is present
  • else alpha-vantage when ALPHA_VANTAGE_API_KEY is present
  • else yahoo-finance2
  • If no provider returns a usable quote, the endpoint returns 400 with a sizing error per symbol.

Auth:

  • API key or ID token

Request fields:

FieldTypeRequiredNotes
strategy / strategy_name / user_strategy_namestringConditionallyOptional only if exactly one strategy exists
targetsarray or object mapYesArray: [{ "symbol": "SPY", "allocation_percent": 33 }] or map: { "SPY": 33 }
execution_anchorenumNonow (default) or next_us_equity_open
execute_on_stock_openbooleanNoAlias for execution_anchor=next_us_equity_open
open_delay_minutesnumberNoApplied per leg
cancel_pending_trades_firstbooleanNoDefault true; set false to preserve the current pending queue
dry_runbooleanNoIf true, returns plan only (no submissions)
idempotency_key / client_order_idstringYesRequired; timeout retries must reuse the identical payload and key
tagsstring[]NoApplied to each submitted leg

Example:

json
{
  "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:

json
{
  "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_ACTIVE with active_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.

ParamRequiredNotes
rebalance_id / rebalanceIdYesID returned by set-target-portfolio

States:

  • accepted: durable job stored
  • planning: worker is pricing, sizing, or submitting legs
  • completed: all required legs were submitted or no trades were needed
  • partially_completed: at least one leg succeeded before a later failure
  • failed: 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:

  1. Persist the payload and idempotency key before submission.
  2. On 202, persist rebalance_id.
  3. Poll until completed, partially_completed, or failed.
  4. If the connection is lost before 202, retry the identical submission with the same key.
  • When cancel_pending_trades_first is enabled, responses also include preflight_pending_trade_reset.
  • If a pending trade is already processing, or cancellation fails during preflight, the job reaches failed before submitting new legs.

Example response fragment:

json
{
  "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:

FieldTypeRequiredNotes
user_strategy_name / strategy_name / strategystringConditionallyOptional only if exactly one strategy exists
assetstringYesSYMBOL or SYMBOL:EXCHANGE
trade_type / side / actionbuy|sellDependsRequired for direct quantity mode
quantity / qtynumberDependsRequired unless allocation is provided
allocation_percent and aliasesnumberDependsRequired unless quantity is provided
fill_policyenumNoimmediate_if_open (default) or next_open_with_delay
open_delay_minutesnumberNonon-negative
idempotency_keystringRecommendedor Idempotency-Key header
tagsstring[]No

Sizing modes:

  1. Quantity mode
  • send quantity + explicit side
  1. Allocation-percent mode
  • send allocation_percent + side
  • quantity is computed from strategy running capital
  1. Target-allocation mode
  • send allocation_percent and 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"):

FieldTypeNotes
import_sourcestringMust equal csv_import
reported_dateISO-8601 stringOptional
user_reported_pricenumberRequired and must be > 0
reference_pricenumberOptional (sizing reference)
allocation_reference_pricenumberOptional (sizing reference)

Optional enrichment fields:

  • rankable_strategy_id, isin, tick_size, multiplier, point_value, margin, commission

Live execution quote behavior:

  • logTrade uses 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_ORDER priority (default alpaca,tradier).
  • Alpaca remains opt-in through ALPACA_EQUITY_ENABLED; Tradier is independently opt-in through TRADIER_EQUITY_ENABLED. Merely configuring TRADIER_ACCESS_TOKEN does 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 include quote_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 to error_processing.

Example provider configuration:

env
ALPACA_EQUITY_ENABLED=true
TRADIER_EQUITY_ENABLED=true
TRADIER_ACCESS_TOKEN=your-production-token
EXECUTION_QUOTE_PROVIDER_ORDER=tradier,alpaca

Tradier 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):

json
{
  "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):

json
{
  "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):

json
{
  "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:

ParamRequiredNotes
strategyName or strategy_nameYesStrategy name
tradeId or trade_idYestradeId or pendingTradeId from submit response

Success (200) returns timeline-style response with:

  • source: pending_trades or strategy_trade
  • current_status: e.g. queued, pending_delay, filled, immutable_stored, verified, error_*
  • snapshot_freshness: not_ready, fresh, stale, unknown
  • execution, filled, timeline

GET /strategy-trades

Get strategy trade history (and optionally pending queue).

Auth:

  • API key or ID token

Query params:

ParamRequiredNotes
strategy_nameYesStrategy name
limitNoDefault 100
include_pendingNotrue/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:

FieldTypeRequiredNotes
strategy_namestringYesStrategy name
pending_trade_idstringYesID from queued trade response
reasonstringNoOptional cancellation note

Success (200):

json
{
  "message": "Pending trade cancelled successfully.",
  "pending_trade_id": "pnd_456",
  "strategy_name": "Sandbox Strategy",
  "status": "cancelled"
}

Possible conflicts:

  • 409 if order is already processing or in another non-cancellable status
  • 404 if 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:

FieldTypeRequiredNotes
strategy_namestringYesStrategy name to clear
reasonstringNoOptional cancellation note applied to all cancelled rows

Success (200):

json
{
  "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:

FieldTypeRequiredNotes
qstringYesquery text
providerstringNoyahoo-finance2, alpha-vantage, twelve-data, coinbase
limitnumberNodefault 10, max 25

Success (200):

json
{
  "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:

FieldTypeRequiredNotes
symbolstringYese.g. AAPL
providerstringNoprovider 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/USD is normalized to BTC-USD
  • bare symbols like BTC are normalized to BTC-USD
  • Crypto symbols are routed to Coinbase first, then fallback providers.

7) cURL Quickstart

1. Set portfolio targets (primary)

bash
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

bash
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)

bash
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

bash
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

  1. Use one API key per integration (webhook, backend service, ETL).
  2. Always send idempotency_key on write requests.
  3. Use validate-trade before enabling production automation.
  4. Alert on repeated 4xx responses.
  5. Poll trade-status for queued trades.
  6. Poll rebalance-status for accepted portfolio submissions.
  7. 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_days field to createStrategy and update-strategy. Controls how many days of recent trades are hidden from public viewers (0, 30, 60, 90, 9999).
  • Added min_rebalance_move_pct field to createStrategy and update-strategy. Legs in set-target-portfolio whose notional move is below this % of running capital are skipped. Default 1.
  • Documented drift filter response fields (drift_filtered, drift_pct) in set-target-portfolio.
  • 0.5 (2026-03-17)
  • Documented set-target-portfolio preflight cancellation of existing pending trades.
  • Documented cancel_pending_trades_first=false opt-out and preflight_pending_trade_reset response field.
  • Clarified request-level replay behavior for set-target-portfolio idempotency retries.
  • 0.4 (2026-03-08)
  • Added POST /cancel-all-pending-trades for 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-portfolio as 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.