GTS Public API

Purpose: connect external tools, scripts, automations, and AI agents to GTS. Use it to read public build schemas, create expressions and strategies, run history/backtests, deploy paper/demo strategies, inspect fired signals, and query account-scoped runtime state. Public docs are open; account data/actions require an API key.

GTS Public API v1 Reference

Use the GTS Public API to let scripts, automations, or AI agents work with GTS accounts safely: read build schemas, create expressions and strategies, run history/backtests, deploy paper/demo strategies, inspect signals, and read runtime stats.

For expression JSON generation, do not start from this full API reference. Use only GET /api/v1/expression-schema and the needed GET /api/v1/expression-schema?type=<ElementType> refs. That scope is complete when the model returns the JSON object or JSON array.

Use this full API reference only for API automation tasks such as saving, strategy management, deployment, history/backtests, signals, or runtime stats.

Quick Start

  1. Open the site and log in.
  2. Go to Settings and copy your API key.
  3. Set BASE and KEY in your terminal.
  4. Call a protected /api/v1/... route with X-API-Key: $KEY.

Production:

BASE=https://gts-trading.com
KEY=<your gts_ api key>

Local development/review:

BASE=<your local or review server URL>

Smoke test the public docs:

curl -s "$BASE/api/v1/docs"
curl -s "$BASE/api/v1/docs?format=html"

Smoke test an authenticated read:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/expressions"

If curl -s "$BASE/api/v1/docs" does not work, BASE is probably not set in that terminal. Run the full URL once:

curl -s "https://gts-trading.com/api/v1/docs?format=html"

Use the expression schema link when you want a model to generate expression JSON.

Use the full API docs only when the task is API automation beyond JSON generation.

Server choices:

Trading server:
https://gts-trading.com

Alert server:
https://gts-alert.com

If the model should generate expression JSON from a trading idea, paste only this instruction:

Read the GTS expression JSON builder schema at https://gts-trading.com/api/v1/expression-schema. For each ElementType you use, read https://gts-trading.com/api/v1/expression-schema?type=<ElementType>. Build only the final expression JSON object or JSON array using values shown by those refs.

Underspecified ideas should return a JSON error instead of guessing the core value. The schema can provide valid values, but it cannot choose the user's main trading concept. For example, "alert me on a candle pattern" is missing the actual pattern name, so the correct result is {"error":"no candle pattern specified"}. Minor defaults such as period 14 or frame 5Min are allowed when implied; the core ElementValue is not guessed.

If the task is strategy/API automation rather than expression JSON generation, then use the full API docs and strategy schema.

Production direct links:

Trading human docs:
https://gts-trading.com/api/v1/docs?format=html

Trading model-readable raw docs:
https://gts-trading.com/api/v1/docs

Trading expression builder schema:
https://gts-trading.com/api/v1/expression-schema

Trading strategy builder schema:
https://gts-trading.com/api/v1/strategy-schema

Alert expression builder schema:
https://gts-alert.com/api/v1/expression-schema

Alert model-readable raw docs:
https://gts-alert.com/api/v1/docs

If the model cannot open links for expression JSON generation, paste the raw text from GET /api/v1/expression-schema, plus only the needed GET /api/v1/expression-schema?type=<ElementType> refs.

Minimal Command Checks

Use these first when testing from a terminal.

Public docs should return markdown:

curl -s -o /tmp/gts_docs.md -w 'HTTP %{http_code} %{content_type}\n' "$BASE/api/v1/docs"

Expected:

HTTP 200 text/markdown; charset=utf-8

Public expression schema should return JSON when requested:

curl -s "$BASE/api/v1/expression-schema?format=json"

Minimal response shape:

{
  "prompt": "string",
  "baseUrl": "https://gts-trading.com",
  "typeReference": "GET https://gts-trading.com/api/v1/expression-schema?type=<ElementType>"
}

Protected routes without a key should fail:

curl -s "$BASE/api/v1/expressions"

Expected:

{
  "success": false,
  "error": "Missing X-API-Key header or logged-in web session"
}

For large catalogs, request a small page:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/symbols?limit=1"

Example response shape:

{
  "symbols": [
    {
      "s": "AAPL",
      "display": "AAPL - Apple Inc.",
      "category": "stock"
    }
  ],
  "count": 1,
  "total": 74000,
  "truncated": true
}

count is the number returned now. total is the full catalog size. truncated: true means the limit kept the response small.

Authentication Rules

  • Public routes are only documentation and build schemas.
  • User data and control routes require either X-API-Key: $KEY or a logged-in web session cookie.
  • The key or session decides the user account. Do not send userId; v1 auth routes ignore it.
  • JSON write routes require Content-Type: application/json.
  • POST /api/account/api-key is different from /api/v1/...: it uses your login cookie, not X-API-Key.

Get An API Key

You do not need an API key to log in. You fetch or copy the API key after login.

Simple cookie flow:

  1. Log in with the normal website login.
  2. The site creates a secure gts_session cookie.
  3. The API key endpoint reads that cookie and identifies your account.
  4. The endpoint returns your API key.
  5. Scripts can now use that key with X-API-Key.

The key endpoint is:

POST /api/account/api-key

It returns:

{
  "api_key": "gts_..."
}

Choose the access flow that matches your account:

Flow A: Google account

Use this when the account signs in with Google.

  1. Open https://gts-trading.com.
  2. Click Continue with Google.
  3. After the site is open, go to Settings.
  4. Copy the API key from the API key panel.
  5. Use that key in external API calls:
BASE=https://gts-trading.com
KEY=gts_...
curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/expressions"

If the Google account has no password set, terminal password login will return google_sso: true. That is expected. Use the browser Google flow, then copy the key from Settings.

Flow B: Email/password account

Use this when the account has a normal site password.

  1. Open https://gts-trading.com.
  2. Log in with email/password.
  3. Go to Settings.
  4. Copy the API key from the API key panel.
  5. Use that key in API calls.

Flow C: Browser-console fetch after login

Open DevTools console while you are logged in on the same site, then run this. The browser automatically sends your login cookie because credentials: 'same-origin' is set:

fetch('/api/account/api-key', { method: 'POST', credentials: 'same-origin' })
  .then(r => r.json())
  .then(console.log)

Flow D: Terminal email/password login

Step 1: log in and save the cookie:

BASE=https://gts-trading.com
curl -s -c /tmp/gts.cookies -H "Content-Type: application/json" \
  -d '{"username":"you@example.com","password":"your-password"}' \
  "$BASE/api/auth/login"

Step 2: use that cookie to fetch the key:

curl -s -b /tmp/gts.cookies -X POST -d '' "$BASE/api/account/api-key"

Step 3: copy the returned api_key value into KEY:

KEY=gts_...
curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/expressions"

Alternative: you can skip the API key and keep using the login cookie for same account API calls:

curl -s -b /tmp/gts.cookies "$BASE/api/v1/expressions"
curl -s -b /tmp/gts.cookies "$BASE/api/v1/signals?limit=20"

This flow only works for accounts that have a site password. It will not work for Google-only accounts unless you first set a password in the account area.

Important:

  • POST /api/account/api-key is not public.
  • POST /api/account/api-key does not accept X-API-Key; it uses your login cookie.
  • Running curl -s -X POST "$BASE/api/account/api-key" alone will fail unless that curl request includes a valid session cookie.
  • Once you have the key, use it on protected /api/v1/... routes with X-API-Key: $KEY.

Flow E: No-login-first fallback

Use this when you do not want to log in first, or when cookie/browser login is not possible.

You must already have a valid API key copied earlier from Settings or supplied by your account/admin. Then call the API like a regular API-key service:

BASE=https://gts-trading.com
KEY=gts_...

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/expressions"
curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/signals?limit=20"
curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/strategies"

If you do not have a key yet, there is no secure no-login way to create one. Creating/fetching a key requires proving account ownership first, either by Google login or email/password login.

If website login fails, POST /api/account/api-key cannot fetch a new key because it needs the login cookie. In that case use an API key you already copied earlier, ask the account owner/admin for a key, or log in through the website later and copy/regenerate the key from Settings.

How to test access:

curl -s "$BASE/api/v1/docs?format=html"
curl -s "$BASE/api/v1/expression-schema"
curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/expressions"
curl -s -b /tmp/gts.cookies "$BASE/api/v1/expressions"

Expected auth failures:

{
  "missingKey": {
    "status": 401,
    "body": {"success": false, "error": "Missing X-API-Key header or logged-in web session"}
  },
  "badKey": {
    "status": 401,
    "body": {"success": false, "error": "Invalid API key"}
  }
}

Public routes:

[
  "GET /api/v1/docs",
  "GET /api/v1/docs?format=html",
  "GET /api/v1/expression-schema",
  "GET /api/v1/expression-schema?type=<ElementType>",
  "GET /api/v1/strategy-schema"
]

Protected routes:

{
  "auth": "Send header X-API-Key: <gts_...>",
  "routes": "All expression, strategy, history, signals, channels, deploy, stats, positions, symbols, community, and permutation APIs"
}

API Return Map

Use this as the quick answer for "what does this API do and what does it return?"

Public docs and schemas

  • GET /api/v1/docs: reads this reference file. Returns text/markdown body, or text/html body when ?format=html.
  • GET /api/v1/expression-schema: reads the expression JSON-builder schema/prompt. Returns text/plain prompt by default, or JSON with type, prompt, baseUrl, and typeReference when ?format=json.
  • GET /api/v1/expression-schema?type=<ElementType>: reads one operand-type reference. Returns allowed values/fields/params for that type as text, or JSON wrapper when ?format=json.
  • GET /api/v1/strategy-schema: reads the strategy builder schema/prompt. Returns text/plain prompt by default, or JSON with prompt, expressionSchema, submitEndpoint, deployEndpoint when ?format=json.

Expressions

  • GET /api/v1/expressions: reads saved expressions. Returns expressions[], count; each expression includes runtimeValid, runtimeValidationErrors, and full_data.
  • GET /api/v1/expression-quota: reads quota counters. Returns success, quota with plan, saved/active usage, limits, and remaining capacity.
  • POST /api/v1/expressions/validate: validates one expression without saving. Returns success, valid, errors[].
  • POST /api/v1/expressions: validates and saves one expression. Returns success, message, expression, planInfo, validatedChannels.
  • POST /api/v1/expressions/update: updates/upserts one expression. Returns success, saved expression, and update metadata.
  • POST /api/v1/expressions/copy: duplicates one expression under a new name. Returns success, saved, source/target names, and copied expression data; returns 404 if source is missing and 409 if target exists.
  • POST /api/v1/expressions/delete: deletes one expression. Returns success and delete status/message.
  • POST /api/v1/expressions/pause: pauses one expression. Returns success and pause status/message.
  • POST /api/v1/expressions/unpause: resumes one expression. Returns success and unpause status/message.

Strategies and handlers

  • GET /api/v1/strategies: reads saved strategies. Returns strategies[], templates[], handlers[], count.
  • POST /api/v1/strategies: saves one strategy plus optional handlers/expressions. Returns success, saved strategy data, and handler/expression save results.
  • POST /api/v1/strategies/copy: duplicates one strategy under a new name, clones strategy-owned slot handlers, and rewires copied slots so the new strategy has no dangling handler references. Shared expression handlers stay shared.
  • POST /api/v1/strategies/delete: removes one saved strategy from the DB library and template/active config files for the key owner.
  • POST /api/v1/strategy-handler: saves one handler. Returns success and saved handler data/status.
  • POST /api/v1/subscribe-strategy: copies/subscribes one shared/generated strategy. Returns success and subscription/copy status.

Permutations and community

  • GET /api/v1/permutations: reads permutation sessions. Returns success, permutation/session list, count.
  • GET /api/v1/permutations/detail: reads one permutation session. Returns success, session metadata, generated strategies[].
  • POST /api/v1/permutations: creates generated strategy variants. Returns success, session id/metadata, generated items, and quota/cap info when applicable.
  • GET /api/v1/community: reads the public community strategy/expression catalog. Returns success, items[], count. This is not the market symbol catalog.
  • GET /api/v1/community/expressions: reads expression cards. Returns success, expressions[], count.
  • GET /api/v1/community/strategies: reads strategy cards. Returns success, strategies[], count.

History/backtest

  • GET /api/v1/history-requests: reads the user's history job queue. Returns success, requests[], count.
  • GET /api/v1/history-requests/quota: reads history quota. Returns success, quota, remaining.
  • GET /api/v1/history-requests/result: reads one completed job result. Returns success, request, manifest, artifacts.
  • POST /api/v1/history-requests: queues a history/backtest job. Returns success, request id, status.
  • POST /api/v1/history-requests/cancel: cancels one history job. Returns success, status.
  • POST /api/v1/history-requests/retry: retries one history job. Returns success, status.

Signals, notifications, and channels

  • GET /api/v1/signals: reads fired alert/signal history. Returns success, count, signals[].
  • GET /api/v1/notification-quota: reads notification quota state. Returns success, quota, remaining.
  • GET /api/v1/channels: reads channel settings. Returns success, count, channels[], configs.
  • GET /api/v1/channel-stats: aggregates delivery results. Returns success, sampleSize, channels grouped by channel name.
  • POST /api/v1/channels: saves channel settings. Returns success and saved channel/status data.

Runtime and market data

  • GET /api/v1/deployed: reads live deployment state. Returns success, count, deployed[].
  • GET /api/v1/stats: reads Trade runtime report stats. Returns success, accountTotal, accountStats[], strategyStats[], perStrategy, perSymbol, reportsAvailable.
  • GET /api/v1/positions: reads Trade runtime position reports. Returns success, count, positions[], reportsAvailable.
  • GET /api/v1/expression-values: reads the key owner's live expression evaluation values (the Monitor "Expressions" tab) from the C++ runtime DB, user-scoped. Query: ?mode=rt|hist (default rt), ?limit=N (default 200, max 5000). Returns success, mode, count, expressionValues[] — each row: strategy, handler, expression, left_name, left_value, operator, right_name, right_value, status, is_alert, event_time, captured_at.
  • GET /api/v1/report: closed-position PnL aggregated by period (the Monitor's Daily/Weekly PnL reports), user-scoped. Query: ?period=daily|weekly (default daily), ?by=account|symbol|strategy (default account), ?mode=rt|hist, ?limit=N (default 60). Returns success, period, by, mode, count, rows[] — each: (symbol|strategy when broken down), period, closed_pnl, positions, wins, losses, gross_profit, gross_loss.
  • GET /api/v1/report/generate: one-call report snapshot for export (the Monitor's "Generate Report"), user-scoped — all closed-PnL aggregates from the DB. Query: ?mode=rt|hist. Returns success, mode, total (account closed-PnL totals), liveAccount (latest live account snapshot; empty when no active session), perStrategy[], perSymbol[], dailyClosedPnl[].
  • GET /api/v1/community/getters: community getter-card catalog (proxied from gts-desk). Returns the getter cards list. GET /api/v1/community/getters/types returns the getter-type list.
  • POST /api/v1/community/publish: publish one of the key owner's strategies to the community (the Monitor's "Share to Community"). Body: strategyName (required), description (empty to auto-generate, else 40-1200 chars). Assembles the strategy + its handlers + the full expression closure (so imports don't break), builds an exec-report from the key owner's ClickHouse run, and uploads to gts-desk under the SaaS community account. Returns success, uploaded, handlers, expressions, symbols, upstream (gts-desk response). Requires COMMUNITY_UPLOAD_EMAIL + COMMUNITY_UPLOAD_API_KEY env (→ 503 if unset).
Per-user data note: expression-values, report, report/generate, stats, and positions are scoped to the key owner via the runtime DB's user_id column (WHERE user_id = <key owner>). They return data only for sessions the runtime has stamped with that real user_id; runtime sessions written without a real user identity (e.g. user_id = "unknown-user") are not visible through the key-scoped API by design. Empty results therefore mean "no user-attributed runtime data yet," not an endpoint failure.

Monitor tab → API mapping

The GUI "GTS DB Monitor" reads the same per-user runtime data these endpoints expose. Each Monitor tab maps to an agent-callable endpoint (the Monitor's Hist/RT toggle = ?mode=hist|rt on every one):

| Monitor tab / section | API endpoint |

| --- | --- |

| Top stat tiles · Overview · Account Details | GET /api/v1/statsaccountTotal / accountStats |

| By Symbol | GET /api/v1/stats (perSymbol) or GET /api/v1/report?by=symbol |

| By Strategy | GET /api/v1/stats (perStrategy) or GET /api/v1/report?by=strategy |

| Open Positions | GET /api/v1/positions?mode=rtopen[] |

| Closed Positions | GET /api/v1/positionsclosed[] |

| Reports (Daily/Weekly PnL) | GET /api/v1/report?period=daily\|weekly |

| Expressions (expression values) | GET /api/v1/expression-values |

| Generate Report (action) | GET /api/v1/report/generate |

| Runtime Strategies (active set) | GET /api/v1/deployed |

| Community getters (builder) | GET /api/v1/community/getters (+ /types) |

| Objects · Logger · Latest Bars · Quotes · Symbol Defs · Charts · Speed Control | not exposed (live-stream / control — deferred; charts are free / BYO-key) |

| Share to Community | not exposed (publish is the one community gap) |

Every stats/reporting/positions tab has an agent equivalent; only the live-stream, control, and publish bits are intentionally out of scope.

  • POST /api/v1/deploy: activates one saved strategy. Returns success, deploy status, and runtime/apply details.
  • POST /api/v1/undeploy: removes one strategy from active runtime. Returns success, undeploy status, and runtime/apply details.
  • POST /api/v1/deploy-batch: deploys multiple strategies. Returns success, results[] with per-strategy status.
  • GET /api/v1/symbols: reads the caller's current market symbol catalog. Returns categories[], symbols[], count, total, truncated. Use ?limit=N for previews so the API does not return the full large catalog.

EDGAR fundamentals

  • GET /api/v1/edgar/reports: proxies EDGAR report catalog. Returns reports.served[], reports.live_only_not_served[], and parameter/auth notes.
  • GET /api/v1/edgar/tickers: proxies EDGAR ticker catalog. Returns tickers[] and count.
  • GET /api/v1/edgar/query: proxies EDGAR fundamental query from URL params. Returns symbol, report_type, columns[], data[], query_ms, and optional message.
  • POST /api/v1/edgar/query: proxies EDGAR fundamental query from JSON body. Returns symbol, report_type, columns[], data[], query_ms, and optional message.

Custom code deployment (Lua and C++)

Ship your own logic — a Lua operand/strategy or a C++ custom handler — entirely over the API, so an agent can author, test, and deploy code on your behalf. Private-runtime plans only: every route below returns 403 with requiresPrivateRuntime: true on shared-runtime plans. Submitted code is parked as pending_review; live execution still passes the human review/certification gate (the reviewer-side approve step is not exposed over the API).

  • GET /api/v1/code/lua: lists submitted Lua scripts and their review state. Query: limit (default 50), includeText=1 to include source. Returns success, scripts[].
  • POST /api/v1/code/lua: submits/parks Lua script text for review. Body: scriptText (or source), optional title, scriptId (to version an existing script). Returns success, script (with scriptId, version, sha256, status).
  • POST /api/v1/code/lua/cancel: cancels an owned Lua review submission. Body: scriptId. Returns success, status.
  • POST /api/v1/code/lua/delete: deletes an owned Lua entry. Body: scriptId, optional version. Returns success, status.
  • GET /api/v1/code/cpp: lists submitted C++ handler bundles and their state. Query: limit (default 50), includeSlots=1 to include source slots. Returns success, scripts[].
  • POST /api/v1/code/cpp: submits/parks a C++ handler bundle. Body: slots (object with the authoring slots), optional title, scriptId. Returns success, script (with scriptId, version, sha256, status).
  • POST /api/v1/code/cpp/dryrun: compiles + runs the bundle in the sandbox and returns console/trace output (or compile errors). Body: slots. Nothing is persisted. Returns success plus debug output.
  • POST /api/v1/code/cpp/deploy: promotes an OWN certified bundle to the live private runtime. Body: scriptId, optional version, libraryPath. Returns success, status.
  • POST /api/v1/code/cpp/cancel: cancels an owned C++ submission. Body: scriptId, optional version. Returns success.
  • POST /api/v1/code/cpp/delete: deletes an owned C++ entry. Body: scriptId, optional version. Returns success.

Response rule:

  • Most routes return {"success": true, ...}.
  • Missing key returns 401.
  • Invalid JSON returns 400.
  • Wrong method returns JSON 405.
  • Unknown v1 route returns JSON 404.

Schema And Discovery

API: GET /api/v1/docs

Name: API documentation

What it does: Serves the full /api/v1 reference document. With ?format=html it returns the browser UI with sections, examples, schemas, and copy buttons. Without format=html it returns the same reference as raw markdown for agents/scripts.

Auth: Public.

How to use:

curl -s "$BASE/api/v1/docs"
curl -s "$BASE/api/v1/docs?format=html"

Request schema:

{
  "query": {
    "format": "html | omitted"
  }
}

Response schema:

{
  "contentType": "text/markdown or text/html",
  "body": "documentation content"
}

API: GET /api/v1/expression-schema

Name: Expression build schema

What it does: Returns the authoritative expression-construction prompt used by agents. The base call gives rules, required JSON keys, operators, frames, and examples. ?type=<ElementType> returns the exact allowed ElementValue, FieldName, and parameter rules for that operand type.

Scope: this endpoint is for generating expression JSON only. A successful answer is the JSON object or JSON array. Validation, saving, deployment, and account actions are separate API automation tasks and are not needed for JSON generation.

Underspecified ideas remain underspecified even with full schema access. Use the per-type refs to choose from values the user actually named or clearly implied. If the user names only a category, return a JSON error such as {"error":"no indicator specified"} or {"error":"no candle pattern specified"}.

Auth: Public.

How to use:

curl -s "$BASE/api/v1/expression-schema"
curl -s "$BASE/api/v1/expression-schema?type=GTSIndicators"
curl -s "$BASE/api/v1/expression-schema?type=ExtendedIndicators"
curl -s "$BASE/api/v1/expression-schema?type=TA_CandlePatterns"
curl -s "$BASE/api/v1/expression-schema?format=json"

Request schema:

{
  "query": {
    "type": "GTSIndicators | ExtendedIndicators | TA_CandlePatterns | OHLC_Bar | Fundamental | ...",
    "format": "json | omitted"
  }
}

Response schema:

{
  "type": "text/plain by default",
  "format=json": {
    "type": "string|null",
    "prompt": "string",
    "baseUrl": "string",
    "typeReference": "string"
  }
}

Regular indicator rule for NLP and agents:

  • Use GTSIndicators for normal indicators: RSI, EMA, SMA, MACD, ATR, BBANDS, STOCH, VWAP, SUPERTREND, etc.
  • Use ExtendedIndicators only for advanced/subsystem indicators: InertialRsi, AdaptiveMacdR2, FvgDetector, OrderBlockDetector, SMC/ICT detectors, ML/regime/adaptive tools.

Minimal regular indicator example: "RSI 14 above 50 on AAPL 5 minute"

{
  "ExpressionName": "RSI14_GT50_5m_AAPL",
  "Expression_left_ElementType": "GTSIndicators",
  "Expression_left_ElementValue": "RSI",
  "Expression_left_Frame": "5Min",
  "Expression_left_Size1": "14",
  "Expression_left_operation": ">",
  "Expression_right_ElementType": "FixedVal",
  "Expression_right_ElementValue": "50",
  "Symbols": ["AAPL"]
}

Minimal extended/subsystem example:

{
  "ExpressionName": "IRSI_GT50_5m_AAPL",
  "Expression_left_ElementType": "ExtendedIndicators",
  "Expression_left_ElementValue": "InertialRsi",
  "Expression_left_Frame": "5Min",
  "Expression_left_FieldName": "signal",
  "Expression_left_operation": ">",
  "Expression_right_ElementType": "FixedVal",
  "Expression_right_ElementValue": "50",
  "Symbols": ["AAPL"]
}

API: GET /api/v1/strategy-schema

Name: Strategy build schema

What it does: Returns the authoritative strategy-construction prompt. It describes the exact JSON shape for strategy, handlers, optional inline expressions, open/close handler slots, handler policies, and the save/deploy sequence.

Auth: Public.

How to use:

curl -s "$BASE/api/v1/strategy-schema"
curl -s "$BASE/api/v1/strategy-schema?format=json"

Request schema:

{
  "query": {
    "format": "json | omitted"
  }
}

Response schema:

{
  "format=json": {
    "prompt": "string",
    "expressionSchema": "string",
    "submitEndpoint": "string",
    "deployEndpoint": "string"
  }
}

Expressions

API: GET /api/v1/expressions

Name: List my expressions

What it does: Reads the key owner's saved expression rows from the SaaS expression store and returns their full JSON definitions. Each item includes runtimeValid and runtimeValidationErrors so expressions that cannot run in GTS are visible before deploy.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/expressions"

Request schema:

{
  "query": {
    "includeSeedCatalogs": "1 | omitted",
    "includeAllUserConfigs": "1 | omitted"
  }
}

Response schema:

{
  "expressions": [
    {
      "name": "string",
      "full_data": {
        "_runtimeValid": true,
        "_runtimeValidationErrors": []
      },
      "runtimeValid": true,
      "runtimeValidationErrors": []
    }
  ],
  "count": 0
}

API: GET /api/v1/expression-quota

Name: Expression quota

What it does: Calculates the key owner's expression quota state: saved expression count, active alert count, plan limits, remaining capacity, and notification-related quota context used by the builder save gate.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/expression-quota"

Request:

No JSON body. No query parameters.

Response schema:

{
  "success": true,
  "quota": {
    "used": 0,
    "active": 0,
    "maxSavedExpressions": 0,
    "maxActiveAlerts": 0,
    "plan": "free|pro|advanced|private"
  }
}

API: POST /api/v1/expressions/validate

Name: Validate expression without saving

What it does: Validates one expression JSON against the same server/runtime rules used by save and deploy: required fields, supported element types, symbols, tree size, blocked legacy types, and runtime compatibility. It never writes to DB, never changes runtime config, and never consumes quota.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"ExpressionName":"IRSI_GT50_5m_AAPL","Expression_left_ElementType":"ExtendedIndicators","Expression_left_ElementValue":"InertialRsi","Expression_left_Frame":"5Min","Expression_left_FieldName":"signal","Expression_left_operation":">","Expression_right_ElementType":"FixedVal","Expression_right_ElementValue":"50","Symbols":["AAPL"]}' \
  "$BASE/api/v1/expressions/validate"

Request schema:

{
  "ExpressionName": "string",
  "Expression_left_ElementType": "string",
  "Expression_left_ElementValue": "string",
  "Expression_left_Frame": "5Min",
  "Expression_left_FieldName": "signal",
  "Expression_left_operation": ">",
  "Expression_right_ElementType": "FixedVal",
  "Expression_right_ElementValue": "50",
  "Symbols": ["AAPL"]
}

Response schema:

{
  "success": true,
  "valid": true,
  "errors": []
}

API: POST /api/v1/expressions

Name: Create expression

What it does: Validates and persists one expression for the key owner. It writes the expression to the SaaS DB, applies runtime config sync, and upserts by ExpressionName if that name already exists.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"ExpressionName":"IRSI_GT50_5m_AAPL","Expression_left_ElementType":"ExtendedIndicators","Expression_left_ElementValue":"InertialRsi","Expression_left_Frame":"5Min","Expression_left_FieldName":"signal","Expression_left_operation":">","Expression_right_ElementType":"FixedVal","Expression_right_ElementValue":"50","Symbols":["AAPL"]}' \
  "$BASE/api/v1/expressions"

Request schema:

{
  "expression": "Expression object, or send the expression object directly"
}

Response schema:

{
  "success": true,
  "message": "Saved <ExpressionName>",
  "expression": {},
  "planInfo": {},
  "validatedChannels": []
}

API: POST /api/v1/expressions/update

Name: Update expression

What it does: Saves a replacement JSON body for an expression name. If expectedUpdatedAt is supplied and the stored row changed since that timestamp, the request is rejected with a stale-write conflict instead of overwriting newer data.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"expression":{"ExpressionName":"IRSI_GT50_5m_AAPL","Expression_left_ElementType":"ExtendedIndicators","Expression_left_ElementValue":"InertialRsi","Expression_left_Frame":"5Min","Expression_left_FieldName":"signal","Expression_left_operation":">","Expression_right_ElementType":"FixedVal","Expression_right_ElementValue":"50","Symbols":["AAPL"]}}' \
  "$BASE/api/v1/expressions/update"

Request schema:

{
  "expression": {},
  "expectedUpdatedAt": "optional timestamp"
}

Response schema:

{
  "success": true,
  "expression": {},
  "updatedAt": "timestamp"
}

API: POST /api/v1/expressions/copy

Name: Copy expression

What it does: Duplicates one saved expression owned by the API-key user under a new ExpressionName. This is save-only: it creates the copied expression but does not deploy it. The source expression is left unchanged. The API returns 404 when the source expression is missing and 409 when the target name already exists.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"name":"IRSI_GT50_5m_AAPL","newName":"IRSI_GT50_5m_AAPL_copy"}' \
  "$BASE/api/v1/expressions/copy"

Request schema:

{
  "name": "existing ExpressionName",
  "newName": "new ExpressionName"
}

Also accepted:

{
  "source": "existing ExpressionName",
  "targetName": "new ExpressionName"
}

Response schema:

{
  "success": true,
  "saved": true,
  "deployed": false,
  "name": "IRSI_GT50_5m_AAPL_copy",
  "source": "IRSI_GT50_5m_AAPL",
  "expression": {}
}

API: POST /api/v1/expressions/delete

Name: Delete expression

What it does: Removes one expression owned by the API-key user from the SaaS DB and updates the user's runtime/config view so the deleted expression is no longer available.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"name":"IRSI_GT50_5m_AAPL"}' "$BASE/api/v1/expressions/delete"

Request schema:

{
  "name": "ExpressionName"
}

Response schema:

{
  "success": true
}

API: POST /api/v1/expressions/pause

Name: Pause expression

What it does: Marks one owned expression as paused/suspended so it remains saved but is excluded from firing/deploy activity.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"name":"IRSI_GT50_5m_AAPL"}' "$BASE/api/v1/expressions/pause"

Request schema:

{
  "name": "ExpressionName"
}

Response schema:

{
  "success": true
}

API: POST /api/v1/expressions/unpause

Name: Unpause expression

What it does: Clears the paused/suspended state for one owned expression so it can be active again.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"name":"IRSI_GT50_5m_AAPL"}' "$BASE/api/v1/expressions/unpause"

Request schema:

{
  "name": "ExpressionName"
}

Response schema:

{
  "success": true
}

Strategies And Handlers

API: GET /api/v1/strategies

Name: List strategies

What it does: Reads the key owner's strategy configuration and returns saved strategies, strategy templates, handler definitions, and counts used by the strategy builder.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/strategies"

Request:

No JSON body. No query parameters.

Response schema:

{
  "strategies": [],
  "templates": [],
  "handlers": [],
  "count": 0
}

API: POST /api/v1/strategies

Name: Save strategy

What it does: Persists one strategy definition for the key owner, including symbol/risk fields and open/close handler references. If inline handlers or expressions are included, those are saved alongside the strategy.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"strategy":{"StrategyName":"demo_strategy","Symbol":"AAPL","OpenHandler1":"demo_open","CloseHandler1":"demo_close"},"handlers":[{"HandlerName":"demo_open","ExpressionsNames":["IRSI_GT50_5m_AAPL"],"Policy":"AND"}]}' \
  "$BASE/api/v1/strategies"

Request schema:

{
  "strategy": {
    "StrategyName": "string",
    "Symbol": "string",
    "OpenHandler1": "string",
    "CloseHandler1": "string",
    "StopLoss": 0,
    "TakeProfit": 0
  },
  "handlers": [],
  "expressions": []
}

Response schema:

{
  "success": true,
  "strategy": {},
  "handlers": []
}

API: POST /api/v1/strategies/copy

Name: Copy strategy

What it does: Duplicates one saved strategy owned by the API-key user under a new StrategyName. The copied strategy is save-only and is not deployed automatically. Strategy-owned slot handlers are cloned and renamed, and the copied strategy's open/close slots are rewired to those cloned handler names so the copy has no dangling handler references. Shared expression handlers that are not named after the strategy stay shared.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"name":"demo_strategy","newName":"demo_strategy_copy"}' \
  "$BASE/api/v1/strategies/copy"

Request schema:

{
  "name": "existing StrategyName",
  "newName": "new StrategyName"
}

Also accepted:

{
  "source": "existing StrategyName",
  "targetName": "new StrategyName"
}

Response schema:

{
  "success": true,
  "saved": true,
  "deployed": false,
  "name": "demo_strategy_copy",
  "source": "demo_strategy",
  "clonedHandlers": [
    "demo_strategy_copy_OpenBid_handler"
  ],
  "writtenDirs": [
    "gts_home/Config/users/<user>",
    "gts_home_private_<user>/Config"
  ]
}

Error behavior:

{
  "404": "source strategy does not exist",
  "409": "target strategy already exists"
}

API: POST /api/v1/strategies/delete

Name: Delete strategy

What it does: Removes one saved strategy owned by the API-key user from the DB strategy library and from the user's template/active strategy config files. This is a saved-library delete, not a runtime restart. If the strategy is active, it is removed from active config as well.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"name":"demo_strategy_copy"}' \
  "$BASE/api/v1/strategies/delete"

Request schema:

{
  "name": "StrategyName"
}

Also accepted:

{
  "strategyName": "StrategyName"
}

Response schema:

{
  "success": true,
  "name": "demo_strategy_copy",
  "removedFromConfigs": 1,
  "removedHandlers": 2
}

API: POST /api/v1/strategy-handler

Name: Save strategy handler

What it does: Persists a config bundle of one or more handler definitions (and optionally strategies/expressions) that bind saved expression names under a fire policy (AND, OR, or SEQUENTIAL). Strategies reference these handlers in open/close slots.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"handlers":[{"HandlerName":"demo_open","ExpressionsNames":["IRSI_GT50_5m_AAPL"],"HandlerExecutionPolicy":"AND"}]}' \
  "$BASE/api/v1/strategy-handler"

Request schema (a bundle — at least one of handlers/strategies/expressions must be non-empty):

{
  "handlers": [
    {
      "HandlerName": "string",
      "ExpressionsNames": ["ExpressionName"],
      "HandlerExecutionPolicy": "AND | OR | SEQUENTIAL"
    }
  ],
  "strategies": [],
  "expressions": []
}

Response schema:

{
  "success": true,
  "handler": {}
}

API: POST /api/v1/subscribe-strategy

Name: Subscribe strategy

What it does: Copies or subscribes the key owner to a strategy produced by the community/permutation flow, making that strategy available in the user's own runtime/config context.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"strategyName":"community_strategy_name"}' "$BASE/api/v1/subscribe-strategy"

Request schema:

{
  "strategyName": "string"
}

Response schema:

{
  "success": true
}

Permutations

API: GET /api/v1/permutations

Name: List permutation runs

What it does: Lists permutation-generation sessions owned by the API-key user, including session metadata and generated strategy batches where available.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/permutations"

Request schema:

{}

Response schema:

{
  "success": true,
  "items": [],
  "count": 0
}

API: GET /api/v1/permutations/detail

Name: Permutation detail

What it does: Returns the generated strategy definitions and metadata for one specific permutation session id owned by the key user.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/permutations/detail?session=<id>"

Request schema:

{
  "query": {
    "session": "string"
  }
}

Response schema:

{
  "success": true,
  "session": {},
  "strategies": []
}

API: POST /api/v1/permutations

Name: Generate permutations

What it does: Generates multiple strategy variants from a base strategy plus parameter ranges, stores the permutation session, and enforces the user's plan cap for generated variants.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"base_strategy":{"StrategyName":"demo_strategy","Symbol":"EURUSD","OpenBidHandler":["demo_open"]},"ranges":{"StopLoss":[10,20],"TP":[30,60]}}' \
  "$BASE/api/v1/permutations"

Request schema (base_strategy is a strategy OBJECT and must include StrategyName):

{
  "base_strategy": { "StrategyName": "string", "Symbol": "string" },
  "ranges": {
    "field": ["values"]
  }
}

Response schema:

{
  "success": true,
  "session": "string",
  "generated": []
}

Community

API: GET /api/v1/community

Name: Community catalog

What it does: Reads the public community catalog and returns shared strategy/expression cards that can be copied into the key owner's workspace.

This endpoint is for reusable community content. It does not return market symbols. Use GET /api/v1/symbols for tradable symbol lookup.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/community"

Request schema:

{}

Response schema:

{
  "success": true,
  "items": [],
  "count": 0
}

API: GET /api/v1/community/expressions

Name: Community expressions

What it does: Returns only reusable community expression cards, including the expression JSON bodies needed to copy them into the user's saved expressions.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/community/expressions"

Request schema:

{}

Response schema:

{
  "success": true,
  "expressions": [],
  "count": 0
}

API: GET /api/v1/community/strategies

Name: Community strategies

What it does: Returns only reusable community strategy cards, including strategy/handler payloads that can be saved into the key owner's strategy workspace.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/community/strategies"

Request schema:

{}

Response schema:

{
  "success": true,
  "strategies": [],
  "count": 0
}

API: GET /api/v1/community/getters

Name: Community getter cards

What it does: Reads the community getter-card catalog (reusable value-getter building blocks), proxied same-origin from the gts-desk community service. Use this to let an agent browse the published getter cards and their details.

Auth: X-API-Key or logged-in web session.

Paths: GET /api/v1/community/getters returns the getter-card catalog; GET /api/v1/community/getters/types returns the getter-type list. (These v1 aliases proxy to the upstream /api/community/getters[...].)

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/community/getters"
curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/community/getters/types"

Response schema: passthrough from the community service (getter cards list / types). On upstream failure returns { "success": false, "error": "getters upstream unavailable: ..." } with HTTP 502.

History Requests

API: GET /api/v1/history-requests

Name: List history requests

What it does: Reads the key owner's history/backtest request queue and returns submitted jobs, queue/running/done/error/cancelled status, timestamps, and identifying metadata.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/history-requests"

Request schema:

{
  "query": {
    "status": "optional",
    "limit": "optional number"
  }
}

Response schema:

{
  "success": true,
  "requests": [],
  "count": 0
}

API: GET /api/v1/history-requests/quota

Name: History quota

What it does: Calculates the key owner's history/backtest quota for the current plan and quota period, including used count, configured limit, and remaining submissions.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/history-requests/quota"

Request schema:

{}

Response schema:

{
  "success": true,
  "quota": {},
  "remaining": 0
}

API: GET /api/v1/history-requests/result

Name: History result

What it does: Fetches the ownership-checked result for one history request id, including manifest and generated report/artifact references when the request completed.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/history-requests/result?id=<uuid>"

Request schema:

{
  "query": {
    "id": "history request id"
  }
}

Response schema:

{
  "success": true,
  "request": {},
  "manifest": {},
  "artifacts": []
}

API: POST /api/v1/history-requests

Name: Submit history request

What it does: Validates the submitted backtest/history payload, applies plan quota, creates a history request row, and queues it for the history worker/runtime to process.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"name":"demo_backtest","strategies":["demo_strategy"],"fromDate":"2024-01-01","toDate":"2024-06-01"}' \
  "$BASE/api/v1/history-requests"

Request schema:

{
  "name": "string",
  "strategies": ["strategy names or strategy objects"],
  "fromDate": "YYYY-MM-DD",
  "toDate": "YYYY-MM-DD",
  "symbol": "optional symbol"
}

Response schema:

{
  "success": true,
  "id": "uuid",
  "status": "queued"
}

API: POST /api/v1/history-requests/cancel

Name: Cancel history request

What it does: Marks one owned history request as cancelled or cancel-requested. Queued jobs stop before execution; running jobs are asked to stop when the worker/runtime supports cancellation.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"id":"<uuid>"}' "$BASE/api/v1/history-requests/cancel"

Request schema:

{
  "id": "history request id"
}

Response schema:

{
  "success": true,
  "status": "cancelled"
}

API: POST /api/v1/history-requests/retry

Name: Retry history request

What it does: Creates or marks a retry for one owned failed/cancelled history request so it can be processed again by the history worker.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"id":"<uuid>"}' "$BASE/api/v1/history-requests/retry"

Request schema:

{
  "id": "history request id"
}

Response schema:

{
  "success": true,
  "status": "queued"
}

Signals Notifications And Channels

API: GET /api/v1/signals

Name: Fired signal history

What it does: Reads the key owner's signal_history rows and returns fired alerts/signals with expression name, symbol, timeframe, channel, send status, timestamp, and details.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/signals?limit=20"

Request schema:

{
  "query": {
    "limit": "1..1000"
  }
}

Response schema:

{
  "success": true,
  "count": 0,
  "signals": [
    {
      "expression_name": "string",
      "symbol": "string",
      "channel": "telegram|email|push|...",
      "status": "sent|failed|other",
      "timestamp": "string",
      "details": "string"
    }
  ]
}

API: GET /api/v1/notification-quota

Name: Notification quota

What it does: Reads the key owner's notification quota state and returns sent counts, limits, remaining alert/external/phone capacity, active period, and plan context.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/notification-quota"

Request schema:

{}

Response schema:

{
  "success": true,
  "quota": {},
  "remaining": {
    "alerts": 0,
    "external": 0,
    "phone": 0
  }
}

API: GET /api/v1/channels

Name: Notification channels

What it does: Reads the key owner's notification channel settings and returns enabled channel names plus stored channel config for email, telegram, webhook, push, SMS/phone, and related delivery targets.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/channels"

Request schema:

{}

Response schema:

{
  "success": true,
  "count": 0,
  "channels": ["telegram", "email"],
  "configs": {}
}

API: GET /api/v1/channel-stats

Name: Channel delivery stats

What it does: Aggregates recent signal_history rows by delivery channel and status bucket, returning per-channel totals for sent, failed, and other outcomes.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/channel-stats?limit=1000"

Request schema:

{
  "query": {
    "limit": "number"
  }
}

Response schema:

{
  "success": true,
  "sampleSize": 0,
  "channels": {
    "telegram": {
      "total": 0,
      "sent": 0,
      "failed": 0,
      "other": 0
    }
  }
}

API: POST /api/v1/channels

Name: Save notification channels

What it does: Validates and saves notification channel configuration for the key owner, updates enable/disable state, enforces plan channel restrictions, and syncs delivery routing config.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"configs":{"telegram":{"enabled":true,"BotToken":"...","ChannelID":"..."}}}' \
  "$BASE/api/v1/channels"

Request schema:

{
  "configs": {
    "telegram": {
      "enabled": true,
      "BotToken": "string",
      "ChannelID": "string"
    },
    "email": {
      "enabled": true,
      "ReceiverEmail": "user@example.com"
    }
  }
}

Response schema:

{
  "success": true,
  "channels": []
}

Deploy And Runtime

API: GET /api/v1/deployed

Name: Deployed strategies/alerts

What it does: Reads the key owner's active/deployed alert and strategy records and returns what is currently live, excluding paused or undeployed items.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/deployed"

Request schema:

{}

Response schema:

{
  "success": true,
  "count": 0,
  "deployed": []
}

API: GET /api/v1/stats

Name: Runtime stats

What it does: Reads the key owner's private runtime report files and returns account totals, account stats, per-strategy stats, and per-symbol stats. Available on the Trade site; Alert site returns not available.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/stats"

Request schema:

{}

Response schema:

{
  "success": true,
  "accountTotal": {},
  "accountStats": [],
  "strategyStats": [],
  "perStrategy": {},
  "perSymbol": {},
  "reportsAvailable": true
}

API: GET /api/v1/positions

Name: Runtime positions

What it does: Reads the key owner's private runtime position reports and returns open/performed positions plus report availability. Available on the Trade site; Alert site returns not available.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/positions"

Request schema:

{}

Response schema:

{
  "success": true,
  "count": 0,
  "positions": [],
  "reportsAvailable": true
}

API: GET /api/v1/expression-values

Name: Live expression values

What it does: Reads the key owner's live expression evaluation values from the C++ runtime database (GTS_REALTIME/GTS_HISTORY session_expressions, scoped to the key owner) — the same data the Monitor "Expressions" tab shows: each leg's left/operator/right, the evaluated value, status, and whether it is an alert. Available on the Trade site.

Auth: X-API-Key or logged-in web session.

Query params: mode=rt|hist (default rt), limit=N (default 200, max 5000).

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/expression-values?mode=rt&limit=200"

Response schema:

{
  "success": true,
  "mode": "rt",
  "count": 1,
  "expressionValues": [
    {
      "session_id": "", "strategy": "", "handler": "", "expression": "",
      "left_name": "", "left_value": "", "operator": "", "right_name": "",
      "right_value": "", "status": "", "is_alert": 0,
      "event_time": "", "captured_at": ""
    }
  ]
}

API: GET /api/v1/report

Name: Closed-PnL report (daily/weekly)

What it does: Aggregates the key owner's closed positions into a daily or weekly PnL report — the same data as the Monitor's Daily/Weekly PnL reports. Closed positions are bucketed by the period of their close time (day, or ISO week), for the whole account or broken down by symbol/strategy. User-scoped via session_closed_positions.user_id. Available on the Trade site.

Auth: X-API-Key or logged-in web session.

Query params: period=daily|weekly (default daily), by=account|symbol|strategy (default account), mode=rt|hist (default rt), limit=N (default 60, max 2000).

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/report?period=daily&by=strategy&limit=30"

Response schema:

{
  "success": true,
  "period": "daily",
  "by": "strategy",
  "mode": "rt",
  "count": 1,
  "rows": [
    {
      "strategy": "", "period": "2026-06-05",
      "closed_pnl": 0, "positions": 0, "wins": 0, "losses": 0,
      "gross_profit": 0, "gross_loss": 0
    }
  ]
}

Notes: when by=account the symbol/strategy field is omitted. closed_pnl = gross_profit + gross_loss for that bucket.

API: GET /api/v1/report/generate

Name: Report snapshot (export)

What it does: Returns a single combined report snapshot for export — closed-PnL account totals, the same broken down by strategy and by symbol, the last 60 days of closed-PnL, plus the latest live account snapshot — mirroring the Monitor's "Generate Report" action. All closed-PnL aggregates come from session_closed_positions (the same reliable source as /api/v1/report); liveAccount comes from session_account_stats and is empty when no session is active. User-scoped. Available on the Trade site.

Auth: X-API-Key or logged-in web session.

Query params: mode=rt|hist (default rt).

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/report/generate"

Response schema:

{
  "success": true,
  "mode": "rt",
  "total": {
    "closed_pnl": 0, "positions": 0, "wins": 0, "losses": 0,
    "gross_profit": 0, "gross_loss": 0
  },
  "liveAccount": {
    "profit": 0, "open_pnl": 0, "closed_pnl": 0, "used_margin": 0,
    "win_ratio": 0, "open_positions": 0, "captured_at": ""
  },
  "perStrategy": [
    { "strategy": "", "closed_pnl": 0, "positions": 0, "wins": 0, "losses": 0, "gross_profit": 0, "gross_loss": 0 }
  ],
  "perSymbol": [
    { "symbol": "", "closed_pnl": 0, "positions": 0, "wins": 0, "losses": 0, "gross_profit": 0, "gross_loss": 0 }
  ],
  "dailyClosedPnl": [
    { "day": "2026-06-05", "closed_pnl": 0, "positions": 0, "wins": 0, "losses": 0, "gross_profit": 0, "gross_loss": 0 }
  ]
}

API: POST /api/v1/deploy

Name: Deploy strategy

What it does: Validates one saved strategy and its referenced expressions, writes the deployed runtime config, and activates that strategy for the key owner's runtime. This is the control path for paper/demo trading.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"strategyName":"demo_strategy"}' "$BASE/api/v1/deploy"

Request schema:

{
  "strategyName": "string"
}

Response schema:

{
  "success": true,
  "deployed": true
}

API: POST /api/v1/undeploy

Name: Undeploy strategy

What it does: Removes one owned strategy from the active runtime deployment set and syncs runtime config so it no longer fires/trades.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"strategyName":"demo_strategy"}' "$BASE/api/v1/undeploy"

Request schema:

{
  "strategyName": "string"
}

Response schema:

{
  "success": true,
  "deployed": false
}

API: POST /api/v1/deploy-batch

Name: Deploy many strategies

What it does: Validates and deploys multiple owned strategies in one batch request, returning per-strategy success/failure results.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"changes":[{"strategyName":"strategy_a","action":"deploy"},{"strategyName":"strategy_b","action":"deploy"}]}' \
  "$BASE/api/v1/deploy-batch"

Request schema (a non-empty changes list; action is deploy or undeploy):

{
  "changes": [
    { "strategyName": "string", "action": "deploy | undeploy" }
  ],
  "deferRestart": false
}

Response schema:

{
  "success": true,
  "results": []
}

Market Data

API: GET /api/v1/symbols

Name: Symbol catalog

What it does: Loads the key owner's current market symbol catalog and returns symbols/categories usable in expressions and strategies.

Important: the catalog can be very large. If you call this endpoint without limit, symbols[] may contain the full catalog. For UI previews or agent validation, call it with ?limit=N.

Return fields:

  • symbols[]: the actual symbols returned in this response.
  • count: how many symbols are in symbols[].
  • total: how many symbols exist in the full catalog.
  • truncated: true when limit capped the returned list.

Auth: X-API-Key or logged-in web session.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/symbols?limit=5"
curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/symbols?limit=100"

Request schema:

{
  "query": {
    "limit": "optional number"
  }
}

Response schema:

{
  "categories": [],
  "symbols": [
    {
      "s": "AAPL",
      "display": "AAPL - Apple Inc.",
      "category": "stock"
    }
  ],
  "count": 5,
  "total": 74000,
  "truncated": true
}

EDGAR Fundamentals

API: GET /api/v1/edgar/reports

Name: EDGAR report catalog

What it does: Proxies to the EDGAR sidecar and returns the catalog of supported fundamental report types that can be queried.

Auth: X-Api-Key accepted by EDGAR sidecar. Paid subscribers only.

Example command:

BASE=https://gts-trading.com
KEY="<paste your real key from Settings > Fundamental Data API>"
curl -s -H "X-Api-Key: $KEY" "$BASE/api/v1/edgar/reports"

If you copy the command with a fake key, the API returns a missing-credentials error. Replace KEY with a real key, or authenticate with your account email using X-User-Email.

Request:

No JSON body. No query parameters.

Example reply from that command:

{
  "reports": {
    "served": [
      "10-K",
      "10-Q",
      "20-F",
      "8-K",
      "Analysis Report",
      "Annual Facts",
      "Balance Sheet",
      "Cash Flow",
      "Income Statement",
      "Quarterly Growth Analysis",
      "Standardized Analysis",
      "Statement Of Equity"
    ],
    "live_only_not_served": [
      "Company Insiders",
      "Insider Holding"
    ],
    "params": {
      "symbol": "ticker, e.g. AAPL (required)",
      "report_type": "one of served (required)",
      "years_from": "annual reports: number of fiscal years back (default 5)"
    },
    "auth": "paid subscribers only"
  }
}

served is the list you can pass as report_type to GET /api/v1/edgar/query or POST /api/v1/edgar/query.

live_only_not_served means the platform recognizes those report names, but they still require a live SEC/EDGAR path and are not served by this public API endpoint yet. Do not use those values as report_type for /api/v1/edgar/query.

Example command for one report:

BASE=https://gts-trading.com
KEY="<paste your real key from Settings > Fundamental Data API>"
curl -s -H "X-Api-Key: $KEY" \
  "$BASE/api/v1/edgar/query?symbol=AAPL&report_type=Income%20Statement&years_from=1"

Example reply for one report:

{
  "symbol": "AAPL",
  "report_type": "Income Statement",
  "columns": [
    "year",
    "revenue",
    "grossProfit",
    "operatingIncome",
    "netIncome",
    "epsDiluted"
  ],
  "data": [
    [2024, 391035000000, 180683000000, 123216000000, 93736000000, 6.08]
  ],
  "query_ms": 42
}

API: GET /api/v1/edgar/tickers

Name: EDGAR ticker catalog

What it does: Proxies to the EDGAR sidecar and returns ticker symbols supported by the EDGAR/fundamental query service.

Auth: X-Api-Key accepted by EDGAR sidecar. Paid subscribers only.

How to use:

curl -s -H "X-Api-Key: $KEY" "$BASE/api/v1/edgar/tickers"

Request:

No JSON body. No query parameters.

Valid successful reply example:

{
  "tickers": [
    {
      "ticker": "AAPL",
      "title": "Apple Inc.",
      "cik": "0000320193"
    },
    {
      "ticker": "MSFT",
      "title": "Microsoft Corporation",
      "cik": "0000789019"
    }
  ],
  "count": 8428
}

API: GET /api/v1/edgar/query

Name: EDGAR fundamental query

What it does: Proxies a GET query to the EDGAR sidecar and returns fundamental records for one symbol/report type filtered by year, quarter, or years_from.

Auth: X-Api-Key accepted by EDGAR sidecar. Paid subscribers only.

How to use:

curl -s -H "X-Api-Key: $KEY" \
  "$BASE/api/v1/edgar/query?symbol=AAPL&report_type=income&years_from=2020"

Request schema:

{
  "query": {
    "symbol": "AAPL",
    "report_type": "income|balance|cashflow|facts|growth|standardized|insiders",
    "year": "optional number",
    "quarter": "optional number",
    "years_from": "optional number"
  }
}

Valid successful reply example:

{
  "symbol": "AAPL",
  "report_type": "Income Statement",
  "columns": [
    "year",
    "revenue",
    "grossProfit",
    "operatingIncome",
    "netIncome",
    "epsDiluted"
  ],
  "data": [
    [2024, 391035000000, 180683000000, 123216000000, 93736000000, 6.08]
  ],
  "query_ms": 42
}

API: POST /api/v1/edgar/query

Name: EDGAR fundamental query by JSON

What it does: Proxies a JSON POST query to the EDGAR sidecar and returns the same fundamental records as the GET query path, using the request body instead of query parameters.

Auth: X-Api-Key accepted by EDGAR sidecar. Paid subscribers only.

How to use:

curl -s -X POST -H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"symbol":"AAPL","report_type":"income","years_from":2020}' \
  "$BASE/api/v1/edgar/query"

Request schema:

{
  "symbol": "AAPL",
  "report_type": "income",
  "year": 2024,
  "quarter": 1,
  "years_from": 2020
}

Valid successful reply example:

{
  "symbol": "AAPL",
  "report_type": "Income Statement",
  "columns": [
    "year",
    "revenue",
    "grossProfit",
    "operatingIncome",
    "netIncome",
    "epsDiluted"
  ],
  "data": [
    [2024, 391035000000, 180683000000, 123216000000, 93736000000, 6.08]
  ],
  "query_ms": 42
}

Custom Code Deployment

Ship your own logic — a Lua operand/strategy or a C++ custom handler — entirely over the API, so an agent can author, test, and deploy code on your behalf. Private-runtime plans only: every route below returns 403 with requiresPrivateRuntime: true on shared-runtime plans. Submitted code is parked as pending_review; live execution still passes the human review/certification gate. The reviewer-side approve step is intentionally NOT exposed over the API — you cannot self-approve your own code.

Typical agent flow: POST .../cpp (submit) → POST .../cpp/dryrun (sandbox test) → wait for certification → POST .../cpp/deploy (go live). Lua follows the same submit/cancel/delete shape without a dryrun.

API: POST /api/v1/code/lua

Name: Submit Lua script

What it does: Validates and parks submitted Lua script text as pending_review. Accepts script text, never filenames or host paths. Pass an existing scriptId to version it.

Auth: X-API-Key or logged-in web session. Private-runtime plans only.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"scriptText":"return 1","title":"my getter"}' "$BASE/api/v1/code/lua"

Request schema:

{
  "scriptText": "string",
  "title": "string (optional)",
  "scriptId": "string (optional — version an existing script)"
}

Response schema:

{
  "success": true,
  "script": { "scriptId": "string", "version": 1, "sha256": "string", "status": "pending_review" }
}

API: GET /api/v1/code/lua

Name: List Lua scripts

What it does: Returns the caller's submitted Lua scripts and their review state. Query: limit (default 50), includeText=1 to include source.

How to use:

curl -s -H "X-API-Key: $KEY" "$BASE/api/v1/code/lua?limit=20"

API: POST /api/v1/code/lua/cancel · POST /api/v1/code/lua/delete

Cancel an owned Lua review submission, or delete an owned entry. Body: {"scriptId":"string"} (delete also accepts optional version). Returns success, status.

API: POST /api/v1/code/cpp

Name: Submit C++ handler bundle

What it does: Validates and parks the C++ custom-handler authoring slots as pending_review. Accepts the authoring slots (not source files). Pass an existing scriptId to version it.

Auth: X-API-Key or logged-in web session. Private-runtime plans only.

How to use:

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"slots":{ "...": "..." },"title":"my handler"}' "$BASE/api/v1/code/cpp"

Request schema:

{
  "slots": { "<authoring slot>": "string" },
  "title": "string (optional)",
  "scriptId": "string (optional)"
}

Response schema:

{
  "success": true,
  "script": { "scriptId": "string", "version": 1, "sha256": "string", "status": "pending_review" }
}

API: POST /api/v1/code/cpp/dryrun

Name: C++ sandbox test run

What it does: Compiles and runs the bundle in the sandbox and returns the debug console output (your log() + per-bar trace, or compile errors). Nothing is persisted. Body: {"slots":{...}}.

API: POST /api/v1/code/cpp/deploy

Name: Deploy C++ handler

What it does: Promotes an OWN certified bundle to the live private runtime. Only a certified version can go live. Body: {"scriptId":"string","version":1,"libraryPath":"string (optional)"}. Returns success, status.

API: GET /api/v1/code/cpp · POST /api/v1/code/cpp/cancel · POST /api/v1/code/cpp/delete

List submitted C++ bundles (query: limit, includeSlots=1), or cancel/delete an owned submission (body: {"scriptId":"string","version":1}).

This section is for agents that are controlling the API. It is not the prompt to use for expression JSON generation.

Confirm the selected server is alive:

BASE=https://gts-trading.com
curl -s -o /tmp/gts_api_check.out -w 'HTTP %{http_code}\n' "$BASE/"

Monitor API and runtime state:

B=https://gts-trading.com
curl -s "$B/api/v1/docs?format=html"              # public docs
curl -s "$B/api/v1/expression-schema"             # expression schema/how-to
curl -s "$B/api/v1/strategy-schema"               # strategy schema/how-to
curl -s -H "X-API-Key: $KEY" "$B/api/v1/deployed" # deployed strategies
curl -s -H "X-API-Key: $KEY" "$B/api/v1/signals?limit=20"
curl -s -H "X-API-Key: $KEY" "$B/api/v1/stats"
curl -s -H "X-API-Key: $KEY" "$B/api/v1/positions"
curl -s -H "X-API-Key: $KEY" "$B/api/v1/channel-stats"

Expression JSON generation flow:

  1. Fetch GET /api/v1/expression-schema.
  2. Fetch every needed GET /api/v1/expression-schema?type=<ElementType>.
  3. Build expression JSON.

API automation flow:

  1. Fetch GET /api/v1/strategy-schema.
  2. Save strategy with POST /api/v1/strategies.
  3. Deploy with POST /api/v1/deploy.
  4. Verify with GET /api/v1/deployed, GET /api/v1/signals, GET /api/v1/stats, and GET /api/v1/positions.