API reference

One HTTP API, and no hidden verbs

JSON over HTTPS, keyed authentication, cursor pagination and idempotent writes. Every endpoint the dashboard uses is an endpoint you can call — there is no private API the product reserves for itself.

Authentication

A bearer token in the header. Keys are scoped, revocable, and never returned after creation.

bash
curl https://api.trade-logx.com/v1/positions \
  -H "Authorization: Bearer $NEXUS_API_KEY" \
  -H "Nexus-Version: 2026-07-01"

Versioning

The Nexus-Version header pins the response shape to a date. Omit it and you get the version your key was created against — never the newest, so a deploy on our side cannot change your parsing.

Rate limits

600 requests per minute per key, 20 per second burst. Limits are returned on every response in X-RateLimit-Remaining; a 429 always carries Retry-After.

Strategies

  • Returns every strategy on the account with its active version, mode (paper or live) and the regimes it is permitted to operate in. Performance is attributed per version, not per strategy, so the response carries the version id you will need for any metrics call.

    example
    {
      "data": [
        {
          "id": "stg_8f21",
          "name": "structure-v4",
          "version": 11,
          "mode": "live",
          "regimes": ["trend", "expanding"],
          "risk_per_trade": 0.005
        }
      ]
    }
  • Changes the execution mode. Promotion is rejected if the strategy has no paper history, if the risk envelope would be breached on the first order, or if the connected venue is degraded. Demotion is always accepted and never closes open positions.

    example
    { "mode": "live" }
    
    → 200 { "id": "stg_8f21", "mode": "live", "effective_at": "2026-07-30T09:14:02Z" }
    → 409 { "error": { "code": "no_paper_history", ... } }

Decisions

  • The rejections are the point. Filter by verdict to retrieve only what was declined and why — over a month this is a more useful record than the trades, because it is the only place you can see what the system nearly did.

    example
    GET /v1/decisions?verdict=veto&since=2026-07-01
    
    {
      "data": [
        {
          "id": "dec_41c9",
          "symbol": "ARB/USDT",
          "conviction": 61,
          "verdict": "veto",
          "vetoed_by": "news_blackout",
          "rationale": "11 minutes to scheduled release; blackout window enforced.",
          "feature_vector_id": "fv_9a2e"
        }
      ]
    }
  • Deterministic. The stored feature vector is fed back through the current model ensemble, which is how you find out whether a change to weights would have altered a decision made months ago. Never places an order.

    example
    {
      "original": { "conviction": 61, "verdict": "veto" },
      "replayed": { "conviction": 68, "verdict": "veto" },
      "diverged": false
    }

Positions

  • Includes the protective orders resident at the venue, so you can verify from outside the product that a stop actually exists rather than trusting that one was requested.

    example
    {
      "data": [
        {
          "symbol": "BTC/USDT", "side": "long", "size": "0.420",
          "entry": 68050.0, "mark": 68776.5, "r_multiple": 1.15,
          "protective": { "stop": 67420.0, "target": 69380.0, "resident": true }
        }
      ]
    }
  • A manual override. It is executed immediately and written to the audit log with the actor and source address, because an override that leaves no trace is indistinguishable from a bug.

    example
    { "reason": "manual flatten before travel" }
    
    → 202 { "order_id": "ord_77b1", "status": "submitted" }

Backtests

  • Runs against the same engine and risk service as live. Sweeps return the whole surface rather than the best cell — a peak surrounded by cliffs is an overfit and the response is shaped so it looks like one.

    example
    {
      "strategy": "structure-v4",
      "symbol": "BTC/USDT",
      "timeframe": "15m",
      "start": "2025-01-01",
      "end": "2026-01-01",
      "sweep": { "threshold": [68, 70, 72, 74, 76] }
    }
    
    → 202 { "id": "bt_2f77", "status": "queued" }
  • Gross performance and cost drag are reported separately. A strategy whose edge disappears once fees, funding and modelled slippage are applied should be visibly that, not quietly netted.

    example
    {
      "status": "complete",
      "gross": { "expectancy": 0.44, "hit_rate": 0.46 },
      "costs": { "fees": -0.09, "funding": -0.02, "slippage": -0.02 },
      "net": { "expectancy": 0.31, "max_drawdown": -0.082 }
    }

Webhooks

The same event envelope the internal bus uses, so a webhook payload and a replayed event are the same object.

envelope
{
  "id": "evt_5c81",
  "type": "decision.vetoed",
  "occurred_at": "2026-07-30T09:18:00.412Z",
  "sequence": 4192837,
  "idempotency_key": "dec_41c9:veto",
  "data": { "...": "the decision object" }
}

Delivery is at-least-once, so handlers must be idempotent — the idempotency_key is stable across retries. Signatures are HMAC-SHA256 over the raw body; verify before parsing. Failed endpoints back off exponentially for 24 hours, and every attempt is visible in the dashboard rather than only in your logs.

Errors

A stable code, a human sentence, and — where a rule caused it — the name of the rule.

StatusCodeMeans
400invalid_requestMalformed body or a parameter outside its allowed range.
401unauthenticatedMissing, malformed or revoked API key.
403insufficient_scopeThe key is valid but not permitted for this operation.
409risk_vetoThe risk service refused the intent. `vetoed_by` names the rule.
422venue_rejectedThe exchange rejected the order; the venue's reason is passed through verbatim.
429rate_limitedRetry after the seconds given in `Retry-After`.
503fail_closedA dependency is unreachable and trading has stopped by design.

503 is not an outage

fail_closed means the risk service is unreachable and trading has stopped deliberately rather than continuing unchecked. Treat it as the system working. Current state is always on the status page.