{"openapi":"3.1.0","info":{"title":"QuantParadox API","description":"Strategy catalog, entitlement and the validated backtest engine.","version":"0.1.0"},"paths":{"/health":{"get":{"tags":["meta"],"summary":"Health","description":"Liveness, plus WHICH BUILD is answering.\n\n[SPEC 2026-08-11] `version` is a hand-set \"0.1.0\" that has not moved in the life of the service,\nso \"did my push actually deploy?\" was unanswerable from outside: /health returned 200 both\nbefore and after a release, and the routes that would reveal a change are behind auth. The owner\nshipped a fix, could not confirm it landed, and had to check by eye in the UI.\n\n`commit` is Render's own `RENDER_GIT_COMMIT`, injected per deploy. It is the git SHA of the\nrunning code and nothing else — no secret, no path, no config. Absent locally, which is the\nhonest answer there: `null` means \"not a Render deploy\", not \"unknown build\".","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Health Get"}}}}}}},"/ready":{"get":{"tags":["meta"],"summary":"Ready","description":"[SPEC 2026-07-22 scalability audit] READINESS (wire the load balancer here, keep /health as\nliveness): a pod with a dead app DB must not receive traffic while reporting 'healthy'.\n\n[SPEC 2026-07-26 deploy fix] The candle archive is checked at the SAME env-overridable path the\nengine reads (QP_CANDLE_DB), not the old hard-coded engine dir — otherwise a disk-mounted archive\nreads as 'missing' forever. And its absence is REPORTED, not fatal, by default: a fresh persistent\ndisk is empty on first boot, so hard-503ing here creates a bootstrap deadlock (the pod can't go\nlive to be shelled-into and seeded). Set QP_READY_REQUIRE_ARCHIVE=1 to restore strict gating once\nthe disk is seeded.\n\n[SPEC 2026-08-10] IT NOW REPORTS FRESHNESS, NOT JUST PRESENCE. `candle_archive: true` answered\n\"is there a file\", which stays green over an archive that stopped ingesting last week — a probe\nthat cannot tell \"we have data\" from \"we have CURRENT data\" is how a console goes green over a\nstale feed. Measured on the live archive the day this shipped: EUR/USD and GBP/USD H1 were 4.2\ndays behind while BTC was 0.6, so the product's core instrument was four days cold.\n\nPER MARKET, NEVER A GLOBAL MAX, and that is the whole point. `SELECT MAX(t) FROM candles` on the\nsame archive returned 0.53 days — healthy-looking — because the freshest market carries the\naggregate and hides every stale one behind it. It also took 180 SECONDS on 24 GB, which would\nhang this very probe; the per-market form is an index seek on ix_candles(market, tf, t) and\nreturns in ~0ms.\n\nREPORTED, NOT FATAL, by default — for the same reason the archive check above is. /ready is this\nservice's healthCheckPath (render.yaml), so 503-ing on stale data would pull the API out of the\nload balancer over a data problem the API cannot fix, and would have taken production down the\nmoment it shipped. Set QP_READY_MAX_ARCHIVE_AGE_DAYS to make it strict once ingest is reliable.","operationId":"ready_ready_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Ready Ready Get"}}}}}}},"/v1/catalog":{"get":{"tags":["catalog"],"summary":"Get Catalog","description":"The strategy catalog for the caller's package.\n\nPublic: anonymous callers are treated as `free` so the marketing site can render the same teaser\nthe app does, from one source of truth. Locked rows are returned WITH their upgrade CTA — the\npaid library is advertised, not hidden. Using it is what requires payment.","operationId":"get_catalog_v1_catalog_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CatalogRow"},"title":"Response Get Catalog V1 Catalog Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/catalog/counts":{"get":{"tags":["catalog"],"summary":"Get Catalog Counts","description":"How many templates each package can USE — for the pricing page, which cannot ask the catalog\nthis question itself.\n\n[SPEC 2026-08-05] Public and unauthenticated, like /v1/catalog: it is marketing copy input. It\nreturns COUNTS ONLY — no ids, no names, no hooks — so the desk roster the leak doctrine protects\nstays protected while the page can still state a true number instead of the 0 it was printing.","operationId":"get_catalog_counts_v1_catalog_counts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"integer"},"type":"object","title":"Response Get Catalog Counts V1 Catalog Counts Get"}}}}}}},"/v1/strategies/{strategy_id}":{"get":{"tags":["catalog"],"summary":"Get Strategy","description":"Full strategy definition — gated. This returns the actual spec/logic, which IS the product,\nso unlike the catalog it requires entitlement.","operationId":"get_strategy_v1_strategies__strategy_id__get","parameters":[{"name":"strategy_id","in":"path","required":true,"schema":{"type":"string","title":"Strategy Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Strategy V1 Strategies  Strategy Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/me":{"get":{"tags":["meta"],"summary":"Me","description":"What this caller is and what they may run — handy for the client to render locks without\nguessing, while the server stays the authority.","operationId":"me_v1_me_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitlementOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/me/onboarding":{"get":{"tags":["meta"],"summary":"Onboarding Get","operationId":"onboarding_get_v1_me_onboarding_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Onboarding Get V1 Me Onboarding Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["meta"],"summary":"Onboarding Put","operationId":"onboarding_put_v1_me_onboarding_put","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Onboarding Put V1 Me Onboarding Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/leads":{"post":{"tags":["leads"],"summary":"Create Lead","description":"Someone wants to talk to a human. Public by necessity — a lead has no account yet.\n\nRequiring a signup before an enterprise buyer can book a demo is how you lose the deal, so this\nstays open and is defended with a honeypot + a per-IP limit rather than a wall.","operationId":"create_lead_v1_leads_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Lead V1 Leads Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/proof":{"get":{"tags":["meta"],"summary":"Proof","description":"The desk's published numbers — a DATED SNAPSHOT, deliberately not a live feed.\n\nPublic and unauthenticated: it is the marketing claim, and the site renders it from here so the\npage can never quote a figure we did not actually produce. Snapshot rather than live because an\nadvertised performance number has to be stable and citable — the same panel read +$14.4k one\nmorning and +$7.2k the same afternoon, and a claim that silently changes between two visits is\nnot a claim. Refresh it on purpose with snapshot_proof.py.\n\nAny figure an admin has hand-edited is overlaid here, so the site and the console can never\ndisagree about what is published. `_edited` lists the overridden paths — the marketing pages do\nnot render it, but it means the published payload always carries its own provenance rather than\nrequiring a database query to reconstruct which numbers a human touched.","operationId":"proof_v1_proof_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Proof V1 Proof Get"}}}}}}},"/v1/content":{"get":{"tags":["meta"],"summary":"Site Content","description":"Copy overrides for the marketing site. Public: it IS the public copy.\n\nReturns overrides ONLY, never defaults. The site ships its own text and applies these on top, so\nan empty table, a cold cache and an unreachable API all render the same correct page. A CMS\nwhose outage blanks the homepage has traded a deploy for an incident.","operationId":"site_content_v1_content_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Site Content V1 Content Get"}}}}}}},"/v1/auth/login":{"post":{"tags":["auth"],"summary":"Login","description":"Email + password -> a session token. For accounts a human set a password on (staff).\n\nService-token gated like provisioning, so this is reachable only from OUR web backend and never\ndirectly from a browser. That is not the security boundary — the password is — but it keeps the\nendpoint off the public internet, which means an attacker cannot grind it without first getting\na foothold on our server.\n\nAlways 401 with the same body, whatever went wrong. See `accounts.LoginFailed`: telling the\ndifference between \"no such user\" and \"wrong password\" hands over a list of which emails are\nstaff, which is the reconnaissance step before the attack.","operationId":"login_v1_auth_login_post","parameters":[{"name":"x-service-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Service-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Login V1 Auth Login Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/provision":{"post":{"tags":["auth"],"summary":"Provision","description":"Turn an ALREADY-VERIFIED identity into a user + workspace + free plan + a session token.\n\nThis endpoint does not authenticate anyone — our web backend does that with the identity\nprovider and vouches with the service token. Idempotent: signing in twice never creates a second\nworkspace or re-grants the welcome credits.","operationId":"provision_v1_auth_provision_post","parameters":[{"name":"x-service-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Service-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Provision V1 Auth Provision Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/credits":{"get":{"tags":["billing"],"summary":"Get Credits","description":"Balance + what the tenant has spent.\n\nEverything that reveals our cost basis is stripped — and that includes the MARKUP multiplier,\nnot just the cost line: `charged / markup` reconstructs our cost exactly, so publishing the\nmultiplier discloses the margin through a side door. Those fields exist for the admin console.","operationId":"get_credits_v1_credits_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Credits V1 Credits Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/credits/ledger":{"get":{"tags":["billing"],"summary":"Get Ledger","operationId":"get_ledger_v1_credits_ledger_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Ledger V1 Credits Ledger Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/checkout":{"post":{"tags":["billing"],"summary":"Checkout","description":"Start a hosted Stripe Checkout. Only an owner/admin can spend the workspace's money.\n[SPEC 2026-07-22 scalability audit] one ACTIVE paid subscription per workspace: N parallel\ncheckouts used to create N live Stripe subscriptions whose events then fought over the tier.","operationId":"checkout_v1_billing_checkout_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Checkout V1 Billing Checkout Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/plans":{"get":{"tags":["billing"],"summary":"Billing Plans","description":"Which billing periods each paid tier can ACTUALLY be bought on, and what we quote for each.\n\nPUBLIC, for the same reason /v1/billing/packs below is: it is the price list a marketing page\nrenders, and /pricing is visible to logged-out visitors. The authenticated /v1/billing overview\nalready carries this payload, but a page with no session cannot call it.\n\n[SPEC 2026-07-30] The pricing page advertised \"Weekly and yearly billing available\" as static\ncopy while every checkout went out monthly — a promise the software did not honour. The fix is\nnot to reword that line, it is to let the page read what is genuinely purchasable: driven by\nwhich Stripe price ids are configured, so an interval appears here only when a checkout on it\nwill actually complete, and an unconfigured one is simply never offered.","operationId":"billing_plans_v1_billing_plans_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Billing Plans V1 Billing Plans Get"}}}}}}},"/v1/billing/packs":{"get":{"tags":["billing"],"summary":"Credit Packs List","description":"The one-time credit packs a user can buy. Public — it is just the price list the app renders.\n\n[SPEC 2026-07-25] reads the DB catalog (api/credit_packs.py) rather than the static config dict,\nso an admin's pricing edit shows up here without a redeploy.","operationId":"credit_packs_list_v1_billing_packs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Credit Packs List V1 Billing Packs Get"}}}}}}},"/v1/billing/credits/checkout":{"post":{"tags":["billing"],"summary":"Credit Checkout","description":"Buy a credit pack (one-time). Owner/admin of the workspace only — it spends money. The webhook,\nnot the success redirect, grants the credits.","operationId":"credit_checkout_v1_billing_credits_checkout_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditCheckoutIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Credit Checkout V1 Billing Credits Checkout Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/alerts":{"get":{"tags":["alerts"],"summary":"List Alerts","operationId":"list_alerts_v1_alerts_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Alerts V1 Alerts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["alerts"],"summary":"Create Alert","operationId":"create_alert_v1_alerts_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Alert V1 Alerts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/alerts/{alert_id}":{"delete":{"tags":["alerts"],"summary":"Delete Alert","operationId":"delete_alert_v1_alerts__alert_id__delete","parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"string","title":"Alert Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Alert V1 Alerts  Alert Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/alerts/hits":{"get":{"tags":["alerts"],"summary":"List Hits","operationId":"list_hits_v1_alerts_hits_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Hits V1 Alerts Hits Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/alerts/check":{"post":{"tags":["alerts"],"summary":"Check Now","description":"Run the check for this workspace now. Free and deterministic — the same evaluation the\nscheduler makes, exposed so a customer can see it work instead of waiting to trust it.","operationId":"check_now_v1_alerts_check_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Check Now V1 Alerts Check Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/benchmarks":{"get":{"tags":["benchmarks"],"summary":"List Runs","description":"The benchmark history for this workspace, newest first.","operationId":"list_runs_v1_benchmarks_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"market","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market"}},{"name":"tf","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tf"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Runs V1 Benchmarks Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/benchmarks/compare":{"post":{"tags":["benchmarks"],"summary":"Compare","description":"Line up 2-6 runs side by side, WITH the reasons they may not be comparable.\n\n`warnings` is the point. Two runs on different markets, timeframes or window lengths produce\nnumbers that look directly comparable and are not — a 2-year run and a 10-year run on the same\nstrategy differ mostly by regime, and picking the prettier one is how a comparison tool teaches\npeople to overfit. We line them up because that is useful, and we say what differs because\notherwise the table quietly lies.","operationId":"compare_v1_benchmarks_compare_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompareIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Compare V1 Benchmarks Compare Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/benchmarks/{run_id}":{"get":{"tags":["benchmarks"],"summary":"Get Run","description":"One run WITH its spec and equity curve — the list deliberately omits both (a history page\nthat ships every spec and curve gets slow), but reloading one into the builder needs them.","operationId":"get_run_v1_benchmarks__run_id__get","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Run V1 Benchmarks  Run Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["benchmarks"],"summary":"Rename Run","description":"Rename a recorded run. The NAME is the only mutable thing here on purpose: the numbers and the\nspec are what happened, and a history you can edit is not a history.","operationId":"rename_run_v1_benchmarks__run_id__patch","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenameIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Rename Run V1 Benchmarks  Run Id  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["benchmarks"],"summary":"Delete Run","operationId":"delete_run_v1_benchmarks__run_id__delete","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Run V1 Benchmarks  Run Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/benchmarks/{run_id}/strategy":{"post":{"tags":["benchmarks"],"summary":"Run To Strategy","description":"Reopen a recorded run in the builder.\n\nThe wizard reopens a SAVED STRATEGY (?load=<sid>), not a run, so the run's spec is minted into\none first — the same strategy /deploy would use. Returns the id the caller should navigate to.","operationId":"run_to_strategy_v1_benchmarks__run_id__strategy_post","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Run To Strategy V1 Benchmarks  Run Id  Strategy Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/benchmarks/{run_id}/deploy":{"post":{"tags":["benchmarks"],"summary":"Deploy Run","description":"Hand a recorded run to the Conscious.\n\nA run is an EVENT, not a strategy (see the BacktestRun docstring), and the desk only evolves\nstrategies — so this SAVES the run's spec as a strategy first, then enrols that. The save is what\nmakes the deploy meaningful: the desk mutates a spec lens-by-lens and reports winners against a\nnamed thing the customer owns, and a run id would leave those winners pointing at a row that\nexists to be immutable.\n\nIdempotent by construction: re-deploying reuses the strategy already minted from this run rather\nthan minting a second copy, and strategies.desk_deploy is itself a no-op when already enrolled.","operationId":"deploy_run_v1_benchmarks__run_id__deploy_post","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Deploy Run V1 Benchmarks  Run Id  Deploy Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/discoveries":{"get":{"tags":["discoveries"],"summary":"List Discoveries","description":"Every condition the engine has flagged across this workspace's recorded backtests.\n\nRead-only and free on every plan: this is the customer's own testing history, and putting a\npaywall on the record of what they already ran would be charging twice. The one-click APPLY is\nwhere the tier gate already lives, and it stays there.\n\nThe default limit matches benchmarks.MAX_KEEP, so the default request sees every run that exists\nrather than a silently truncated slice of it. The true row count is passed separately regardless,\nbecause the \"runs that pre-date recording\" caveat must stay right even when a caller asks for\nfewer.","operationId":"list_discoveries_v1_discoveries_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":500,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Discoveries V1 Discoveries Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/leaderboard":{"get":{"tags":["leaderboard"],"summary":"Board","description":"The board. Every published strategy, with its statistics recomputed from stored records.\n\nOrdering is left to the caller: the same rules are implemented in the web app's board.ts so they\ncan be unit-tested without a database, and both read the same fields.","operationId":"board_v1_leaderboard_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Board V1 Leaderboard Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/leaderboard/eligibility/{strategy_id}":{"get":{"tags":["leaderboard"],"summary":"Eligibility","description":"Would this strategy be RANKED if it were published right now, and if not, why?\n\n[SPEC 2026-08-08] This exists so a Publish button can tell the truth BEFORE it is pressed. The\nevolved-strategy card that prompted it is the exact case: \"best of 42 lens combinations, confirmed\non 11 sealed trades ... p=0.78\". Publishing that is legitimate — the record is real and public —\nbut it lands unranked, and a button that said only \"Publish\" would have quietly moved a proud\nmoment into a block labelled \"not yet proven\". Better to say so on the button.","operationId":"eligibility_v1_leaderboard_eligibility__strategy_id__get","parameters":[{"name":"strategy_id","in":"path","required":true,"schema":{"type":"string","title":"Strategy Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Eligibility V1 Leaderboard Eligibility  Strategy Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/leaderboard/publish":{"post":{"tags":["leaderboard"],"summary":"Publish","description":"Put one of YOUR OWN strategies on the board. Idempotent: publishing twice updates the price.\n\nNothing in the body is a performance claim — only an id and a price. Every number the board shows\nis recomputed server-side from the stored record, so there is no field here a client could use to\nadvertise a result it did not earn.","operationId":"publish_v1_leaderboard_publish_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Publish V1 Leaderboard Publish Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/leaderboard/unpublish":{"post":{"tags":["leaderboard"],"summary":"Unpublish","description":"Take it off the board. Existing follows are left alone rather than cascaded away: someone\nalready paid for a period, and deleting the record they paid to watch would be the owner\ncancelling a purchase the follower made.","operationId":"unpublish_v1_leaderboard_unpublish_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StrategyBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Unpublish V1 Leaderboard Unpublish Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/leaderboard/follow":{"post":{"tags":["leaderboard"],"summary":"Follow","description":"Follow a published strategy's performance.\n\nWHAT MOVES: with QP_FOLLOW_BILLING off — the default — a follow row is written, the owner's share\nis COMPUTED AND RECORDED, and no credit is debited and no payout is made. That is deliberate: the\naccrual is the part worth getting right early, and it can be reconciled against real charges the\nday billing is switched on.\n\nThe unique constraint on (workspace, strategy) is the double-click guard. Re-following an already\nfollowed strategy is a no-op rather than a second charge.","operationId":"follow_v1_leaderboard_follow_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StrategyBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Follow V1 Leaderboard Follow Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/leaderboard/earnings":{"get":{"tags":["leaderboard"],"summary":"Earnings","description":"What this workspace has earned as an AUTHOR — per strategy, plus what actually landed.\n\nTWO NUMBERS, AND THEY ARE ALLOWED TO DISAGREE. `accrued` sums the share stamped on each billed\nfollow; `credited` sums the ledger rows actually written to this workspace. They match for\neverything followed after the author share started being paid, and they do NOT match for follows\nbilled before it — those charged the follower and credited nobody. Reporting one number would\neither hide that gap or invent a payment.\n\nNothing is claimed about cash: the share is credits, spendable on the platform. No money leaves\nthe system, which is exactly why this needs no payout provider.","operationId":"earnings_v1_leaderboard_earnings_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Earnings V1 Leaderboard Earnings Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/leaderboard/unfollow":{"post":{"tags":["leaderboard"],"summary":"Unfollow","operationId":"unfollow_v1_leaderboard_unfollow_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StrategyBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Unfollow V1 Leaderboard Unfollow Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/leaderboard/feed":{"get":{"tags":["leaderboard"],"summary":"Feed","description":"Entries and exits on the strategies this workspace follows, oldest first.\n\nA PULL. The client asks with a cursor and gets what is already recorded; nothing is delivered,\nscheduled or pushed to anyone. `since` is an EVENT ID rather than a timestamp, so a client that\nwas offline across a clock change — or that follows a strategy whose record carries no times at\nall — cannot silently skip a run of events.\n\nOnly strategies this workspace actually follows are read, and only their out-of-sample record.\nFollowing buys sight of a track record, not of the spec: no rule, filter or parameter of the\nstrategy appears here, because that is the thing the owner is not selling.","operationId":"feed_v1_leaderboard_feed_get","parameters":[{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Since"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Feed V1 Leaderboard Feed Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/forgot":{"post":{"tags":["auth"],"summary":"Forgot","description":"Ask for a reset link. ALWAYS answers the same thing.","operationId":"forgot_v1_auth_forgot_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/reset":{"post":{"tags":["auth"],"summary":"Reset","description":"Spend a token and set the password.\n\nReturns ok=False with a reason rather than raising: this is a form, the reasons are all things\nthe person can act on (\"it expired, ask for another\"), and none of them reveal anything about\nan account they are not already holding a token for.","operationId":"reset_v1_auth_reset_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing":{"get":{"tags":["billing"],"summary":"Overview","description":"Plan + payment method + payment history, in one call.\n\n`payments` is built from OUR ledger, not from Stripe, so the history renders instantly and still\nworks when Stripe is unreachable — the ledger is append-only and is already the record we would\nreconcile a dispute against.","operationId":"overview_v1_billing_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Overview V1 Billing Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/portal":{"post":{"tags":["billing"],"summary":"Portal","description":"A one-time link into Stripe's hosted billing portal — update card, change or cancel plan,\ndownload receipts. We deliberately do not rebuild any of that: the portal handles proration and\ndunning correctly, and keeping card entry on Stripe's domain is what keeps us out of PCI scope.","operationId":"portal_v1_billing_portal_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Portal V1 Billing Portal Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/cancel/preview":{"get":{"tags":["billing"],"summary":"Cancel Preview","description":"What actually stops if this subscription ends. Assembled from rows, not from marketing.","operationId":"cancel_preview_v1_billing_cancel_preview_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Cancel Preview V1 Billing Cancel Preview Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/notifications":{"get":{"tags":["notifications"],"summary":"List Notifications","operationId":"list_notifications_v1_notifications_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":30,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Notifications V1 Notifications Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/notifications/{nid}/read":{"post":{"tags":["notifications"],"summary":"Mark Read","operationId":"mark_read_v1_notifications__nid__read_post","parameters":[{"name":"nid","in":"path","required":true,"schema":{"type":"string","title":"Nid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Mark Read V1 Notifications  Nid  Read Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/notifications/read_all":{"post":{"tags":["notifications"],"summary":"Mark All Read","operationId":"mark_all_read_v1_notifications_read_all_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Mark All Read V1 Notifications Read All Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/notifications/preferences":{"get":{"tags":["notifications"],"summary":"Get Preferences","operationId":"get_preferences_v1_notifications_preferences_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Preferences V1 Notifications Preferences Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["notifications"],"summary":"Set Preferences","operationId":"set_preferences_v1_notifications_preferences_patch","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrefsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Set Preferences V1 Notifications Preferences Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/notifications/unsubscribe":{"get":{"tags":["notifications"],"summary":"Unsubscribe","description":"One click, no login. Turns OFF email only — the in-app feed is unaffected, because someone\nwho wants less mail has not asked to lose the product's notifications.\n\nUnauthenticated by design: an unsubscribe link that demands a password is one people report as\nspam instead of clicking, and that costs the sending domain far more than the mail was worth.\nThe token is a per-user secret and grants nothing else.","operationId":"unsubscribe_v1_notifications_unsubscribe_get","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Unsubscribe V1 Notifications Unsubscribe Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/retention/health":{"get":{"tags":["retention"],"summary":"Workspace Health","description":"This workspace's own engagement picture. Deliberately visible to the customer, not just to\nus: \"you have three strategies and haven't run one in twelve days\" is more useful to them than\nit is to our churn dashboard.","operationId":"workspace_health_v1_retention_health_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Workspace Health V1 Retention Health Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/retention/digest":{"get":{"tags":["retention"],"summary":"Digest","description":"\"What your subscription earned you\" — the flagship retention artifact.\n\nAggregates only things that actually happened. Note what is NOT here: no projected returns, no\n\"you could have made\", no annualised anything. The headline `learning_impact` is MEASURED\nattribution read from the desk, and when the desk cannot be reached the field is absent rather\nthan estimated — a digest that invents its headline is worse than no digest, because the reader\nfinds out eventually and stops believing the true parts too.\n\n`renews_at` is included because the digest is timed to land a few days before it. The point of\nthe artifact is to make the renewal decision an informed one, not to hide it.","operationId":"digest_v1_retention_digest_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":31,"minimum":1,"default":7,"title":"Days"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Digest V1 Retention Digest Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/retention/proof":{"get":{"tags":["retention"],"summary":"Proof Progress","operationId":"proof_progress_v1_retention_proof_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Proof Progress V1 Retention Proof Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/retention/improvements":{"get":{"tags":["retention"],"summary":"Improvements","description":"Evolved challengers the brain has found and sealed, ready for the customer to promote.\n\nWe never auto-promote. The loop is \"staying subscribed means your strategy keeps improving while\nyou sleep\" — but the improvement is always a nudge someone acts on, never a change made to their\nstrategy without them. That line is the difference between a research tool and a black box.\n\nReturns an empty list with an explicit reason when the desk is unreachable, so the UI can say\n\"we could not check\" instead of \"you have no improvements\" — the same false-negative that made\nthe brain tell customers they had no strategies.","operationId":"improvements_v1_retention_improvements_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Improvements V1 Retention Improvements Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/retention/decay/refresh":{"post":{"tags":["retention"],"summary":"Refresh Decay","description":"Recompute health now. Exposed so the UI can offer a refresh rather than making someone wait\nfor the next scheduled sweep.","operationId":"refresh_decay_v1_retention_decay_refresh_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Refresh Decay V1 Retention Decay Refresh Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/retention/decay":{"get":{"tags":["retention"],"summary":"Decay Radar","description":"Which of this workspace's strategies are drifting away from the backtest that sold them.\n\nRefreshes LAZILY when the rows have gone stale — same reasoning as the paper records: there is no\ncron service, and a radar that only updates when someone remembers to press a button is not a\nradar. Best-effort: a failed sweep returns the rows we already have, because a slightly old\nhealth score beats a broken page.","operationId":"decay_radar_v1_retention_decay_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Decay Radar V1 Retention Decay Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/markets":{"get":{"tags":["wizard"],"summary":"Markets","description":"What the archive can actually backtest — the wizard offers only these, so a picker can never\npoint at a market with no history.\n\n[SPEC 2026-07-28] Also reports `max_days`, the platform's real lookback ceiling, for the same\nreason the market list exists: a picker must not offer something the engine will silently refuse.\nThe history dropdown offered 6/8/10 years against a 4-year cap, so a customer could select a\ndecade, be tested on four years, and be told the coverage was full.\n\n[SPEC 2026-08-04] That ceiling is PER TIMEFRAME now, so one number can no longer be right. The\nsame ten years costs 59k bars on H1 and 4.5M on M1; `max_days_by_tf` is what the picker should\nread, and the flat `max_days` stays only so an older client keeps working — it reports the most\npermissive value, which is the safe direction for a hint whose only job is to hide options the\nserver would refuse anyway. The server clamps regardless; this endpoint exists so the refusal\nis visible in the dropdown instead of arriving as a surprise in the coverage note.","operationId":"markets_v1_wizard_markets_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Markets V1 Wizard Markets Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/resolve_symbol":{"get":{"tags":["wizard"],"summary":"Resolve Symbol","description":"Is this a real US ticker? — so the picker can offer any listing, not a shortlist of 43.\n\n[SPEC 2026-08-11] `/markets` returns the instruments we OFFER, which for equities is a curated\nlist meant to be discoverable. It was also, wrongly, the only set that could be traded: four\nseparate layers refused anything outside it, so PLTR, COIN and UBER could not be sized, costed or\nbacktested at all. The agreed design was that the archive holds what is DEPLOYED and the vendor\nserves what is ASKED FOR, and this route is the \"asked for\" half.\n\nAnswers only the identity question. It writes nothing and reserves nothing; the backtest that\nfollows fetches the real window through the ordinary path, so there is still exactly one way bars\nreach a strategy.\n\nRefusals are the point rather than an edge case: a mistyped ticker must come back as \"no US-listed\nprice history for XYZQ\" while the customer is still looking at the box, not as an empty chart\nlater. The shape check runs first so a junk string never becomes a paid vendor request.","operationId":"resolve_symbol_v1_wizard_resolve_symbol_get","parameters":[{"name":"symbol","in":"query","required":true,"schema":{"type":"string","title":"Symbol"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Resolve Symbol V1 Wizard Resolve Symbol Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/candles":{"get":{"tags":["wizard"],"summary":"Candles","description":"[SPEC 2026-07-31] Chart data feed — candles for [frm, to] at tf, from the SAME loader the\nbacktest reads, so the price chart and the engine can never tell two different stories about a\nbar. Read-only archive data; any signed-in principal may read it (same gate as /markets).","operationId":"candles_v1_wizard_candles_get","parameters":[{"name":"market","in":"query","required":true,"schema":{"type":"string","title":"Market"}},{"name":"tf","in":"query","required":true,"schema":{"type":"string","title":"Tf"}},{"name":"frm","in":"query","required":true,"schema":{"type":"integer","title":"Frm"}},{"name":"to","in":"query","required":true,"schema":{"type":"integer","title":"To"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Candles V1 Wizard Candles Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/read_chart":{"post":{"tags":["wizard"],"summary":"Read Chart","description":"[SPEC 2026-07-28] A chart screenshot -> a strategy DESCRIPTION the trader confirms.\n\nDeliberately returns English, not a strategy. A chart shows what HAPPENED, never what the RULE\nwas — arrows at three swing lows fit \"buy the swing low\", \"buy the retest after a sweep\" and\n\"buy when RSI < 30\" equally well, and a backtest of the wrong rule is exactly as convincing as a\nbacktest of the right one. The read lands in the description box, where it can be corrected\nbefore anything is built, and then flows through the normal /author path.\n\nCHARGES CREDITS (vision call). Same HOLD -> work -> SETTLE discipline as /author: a row-locked\ndebit at the ceiling lands before the call, the unused part is refunded, and ANY failure refunds\nthe whole hold — a read we could not deliver is never billed.","operationId":"read_chart_v1_wizard_read_chart_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChartReadIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Read Chart V1 Wizard Read Chart Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/ideas":{"get":{"tags":["wizard"],"summary":"Ideas","description":"[SPEC 2026-07-28] BRAINSTORM — testable strategy ideas, each with the evidence behind it.\n\nFree and deterministic: rendered straight from the validated research corpus, with NO AI call.\nThat is deliberate — an LLM riffing over the same corpus would cost credits, be slower, and could\ndrift into citing a study that does not exist. Every line here traces to a real one.\n\nShips the REJECTED findings too. \"Fading every liquidity sweep is ~0R over 87,000 samples\" is\nworth more to a trader than another indicator combination, and it is the part a competitor\ncannot copy — not because the code is hard, but because they never ran the study.","operationId":"ideas_v1_wizard_ideas_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Ideas V1 Wizard Ideas Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/mode_evidence":{"get":{"tags":["wizard"],"summary":"Mode Evidence","description":"[SPEC 2026-07-30] What OUR studies say about each backtester filter, keyed by mode id.\n\nThe filter cards already say what a mode is and how recent its signal is; this is the slot only\nwe can fill. It ships the REJECTED findings in the same shape as the validated ones — someone\nticking \"fade every sweep\" sees, at that moment, that 87,000 samples found no edge there. A\nplatform that sells backtesting and hides its own negative results is selling hope.\n\nFree, deterministic, no AI: rendered from `engine/knowledge.py` with an EXPLICIT mode→study\nmapping. Fuzzy concept matching was rejected for exactly this surface — the evidence-graph work\ncaught keyword overlap fabricating citations three times, and a filter card is a citation.\nModes with no matching study return an empty list, which the UI states plainly rather than\nhiding.","operationId":"mode_evidence_v1_wizard_mode_evidence_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Mode Evidence V1 Wizard Mode Evidence Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/starters":{"get":{"tags":["wizard"],"summary":"Starters","description":"The pre-built starter templates — vanilla, well-understood strategies as a one-click on-ramp.\nEvery tier SEES all of them (locked ones are teased with the tier that unlocks them), but the\nrunnable `spec` is included ONLY for the ones this tier may use, so a gated spec never crosses the\nwire. Each spec is a validated, backtestable strategy the wizard can load straight into the tester.","operationId":"starters_v1_wizard_starters_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Starters V1 Wizard Starters Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/author":{"post":{"tags":["wizard"],"summary":"Author","description":"English (or pasted Pine/MQL/Python) -> a validated strategy the engine can run. CHARGES CREDITS.\n\n[SPEC 2026-07-22 scale audit] money path is HOLD -> work -> SETTLE: a row-locked debit at the\ncost ceiling (credits.spend) lands BEFORE the AI call — two parallel requests can no longer both\npass an unlocked balance read and overdraw the workspace. After the call the unused part of the\nhold is refunded (settle), so the net equals our real metered cost * markup; on any failure the\nfull hold is refunded. The ledger keeps both rows, so a dispute reads line by line.\n\n[SPEC 2026-08-30] EXACTLY ONE HOLD PER PATH, and each is settled by the code that opened it:\ncode-first bills inside _author_sdk_metered, the rules author bills below. The hold used to sit\nabove the branch, where code-first never settled it — so every build on the new default path\nburned the ceiling on top of its real cost, whether it succeeded or was refused. If a third\npath is ever added here, it opens its own hold and settles it on EVERY exit, including the\nraises; a hold that outlives its branch is money taken for nothing delivered.","operationId":"author_v1_wizard_author_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Author V1 Wizard Author Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/author_sdk":{"post":{"tags":["wizard"],"summary":"Author Sdk","description":"Author a strategy as real SDK CODE. CHARGES CREDITS (same HOLD -> work -> SETTLE path as\n/author: a row-locked debit at the ceiling before the AI call, unused part refunded, full refund\non any failure). Call this only after /author reported `unsupported` — the spec is the better\nartifact whenever it can express the strategy.","operationId":"author_sdk_v1_wizard_author_sdk_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Author Sdk V1 Wizard Author Sdk Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/backtest_sdk":{"post":{"tags":["wizard"],"summary":"Backtest Sdk","description":"Backtest SDK strategy code on real history — ALWAYS in the isolated worker, never here.\nFree (no AI), authenticated and quota-capped like the spec backtest.","operationId":"backtest_sdk_v1_wizard_backtest_sdk_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SdkBacktestIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Backtest Sdk V1 Wizard Backtest Sdk Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/modules":{"get":{"tags":["wizard"],"summary":"Wizard Modules","description":"[SPEC 2026-08-28] Which optional pieces of the wizard are switched on.\n\nFree and unmetered on every tier — it is one small indexed read, and a panel that renders\ndifferently depending on whether you could afford to ask would be indefensible. Default is ON,\nso an unreachable flag store shows the product as designed rather than a stripped panel.","operationId":"wizard_modules_v1_wizard_modules_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Wizard Modules V1 Wizard Modules Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/read_spec":{"post":{"tags":["wizard"],"summary":"Read Spec","description":"[SPEC 2026-08-28] WHICH INSTRUMENT AND BAR SIZE DID THEY JUST TYPE?\n\nThe wizard's pickers used to sit on their defaults while someone typed \"Backtest this XAUUSD\nstrategy on 5-minute candles\" beside them, and the panel said BTC / M15 the whole time. The\nengine has read the text since 2026-08-24 (_apply_read_spec) — but only inside the paid build,\nand the wizard threw the answer away, so the picker stayed wrong right through the results.\n\nFREE, UNMETERED, EVERY TIER. It is string matching, no model and no archive read: metering it\nwould put a price on being told what you already typed, and gating it would leave exactly the\nfree-tier customers this misleads paying nothing and seeing the wrong instrument.\n\nReturns the same shape the build path uses (`market`, `tf`, `missing`) from the SAME reader, so\nthe live hint and the built spec cannot disagree about what a sentence says.","operationId":"read_spec_v1_wizard_read_spec_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadSpecIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Read Spec V1 Wizard Read Spec Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/lens":{"post":{"tags":["wizard"],"summary":"Custom Lens","description":"[SPEC 2026-07-23] CUSTOM MODE: plain English -> a validated lens (sessions/trend/vol/news/\nexits + compile-checked entry conditions). Enterprise-only like the other modes; metered\nHOLD->SETTLE at a small ceiling; a failed call refunds in full.","operationId":"custom_lens_v1_wizard_lens_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LensIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Custom Lens V1 Wizard Lens Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/backtest":{"post":{"tags":["wizard"],"summary":"Backtest","description":"Run the strategy on real history and return exact trades, PnL and stats. Free (no AI), but\nauthenticated, quota-capped (429) and bounded by the engine's capacity gate (503).\n\n[SPEC 2026-07-22] MULTI-MODE: `modes` composes behavioral lenses onto the run — sessions\n(London/NY hours only), regime (trade with the trend), news (skip entries near red calendar\nevents). ENTERPRISE-ONLY, enforced HERE not just in the UI: any other tier gets the 403 paywall\nshape naming the tier that unlocks it — a paywall, not a secret.","operationId":"backtest_v1_wizard_backtest_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__wizard__BacktestIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Backtest V1 Wizard Backtest Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/backtest/progress/{job_id}":{"get":{"tags":["wizard"],"summary":"Backtest Progress","description":"Poll a running backtest. Free, cheap, and scoped to the caller's workspace — a job id is\nclient-minted and therefore guessable, so the ROW is what enforces tenancy, not the id.\n\nAn unknown id answers `known: false` rather than `pct: 0`: \"we have no reading\" and \"this run\nis 0% done\" are different facts, and a bar frozen at the start is how a progress indicator\nstarts lying.","operationId":"backtest_progress_v1_wizard_backtest_progress__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Backtest Progress V1 Wizard Backtest Progress  Job Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/trade_evidence":{"post":{"tags":["wizard"],"summary":"Trade Evidence","description":"[SPEC 2026-07-28] WHY did this trade happen — bars window + the engine's own structural\noverlays + the spec's literal predicates evaluated at the signal bar. Free: deterministic CPU,\nderived (never stored), and the trust it builds is the product.","operationId":"trade_evidence_v1_wizard_trade_evidence_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvidenceIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Trade Evidence V1 Wizard Trade Evidence Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/screen":{"post":{"tags":["wizard"],"summary":"Screen","description":"[SPEC 2026-07-28] THE SCREENER — where is this strategy's setup firing right now, and what\nhas that exact setup been worth on that exact market?\n\nA signal service says \"BUY EURUSD\". This says \"fired, and here is its measured history here\".\nThe second half is the only reason to act on the first, and it is what a signal vendor cannot\ncompute. Deterministic CPU, no AI: free, like the backtest itself.","operationId":"screen_v1_wizard_screen_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScreenIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Screen V1 Wizard Screen Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/export_bundle":{"post":{"tags":["wizard"],"summary":"Export Bundle","description":"[SPEC 2026-07-28] THE ENGINE-BUNDLED EXPORT as a downloadable zip: run_strategy.py +\nstrategy_spec (embedded) + qbt_engine.py + README. This is the export that cannot fail — it\nruns the real engine, so it reproduces the backtest trade-for-trade for ANY spec, including the\nlevel/structure strategies standalone Python has no way to re-implement.\n\nPro and above, like /export — and gated here even though no UI currently calls this route (the\nwizard declares an `onExportBundle` prop it never passes). An uncalled route is still a reachable\none, and this is the MOST complete export we ship: the engine itself.","operationId":"export_bundle_v1_wizard_export_bundle_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/wizard/export":{"post":{"tags":["wizard"],"summary":"Export","description":"Logic graph -> TradingView Pine v5, MetaTrader MQL5, standalone Python, or QuantConnect LEAN.\n\nPro and above (EXPORT_TIERS). Gated BEFORE the generation call, not after: refusing a free\ncaller should cost us nothing, and a 403 carrying the code in a field the client \"shouldn't\"\nread is not a gate at all.","operationId":"export_v1_wizard_export_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Export V1 Wizard Export Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/external/backtest":{"post":{"tags":["external-signals"],"summary":"Backtest","description":"Run the customer's own entries through the engine's execution model.\n\nReturns the SAME payload shape a wizard backtest returns — stats, walk-forward, luck-of-the-draw,\ncoverage, filter health — because it runs the identical code path. The only additions are\n`causality` (what the number does and does not prove) and `signals_used`.","operationId":"backtest_v1_external_backtest_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__external_signals__BacktestIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Backtest V1 External Backtest Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/external/forward/{sid}":{"post":{"tags":["external-signals"],"summary":"Forward","description":"Record ONE signal for a bar that has not closed yet.\n\nTHIS IS THE GATE, and it is the reason the forward record means something. A signal is accepted\nonly while its bar is still open: `bar_t <= now < bar_t + tf`. Arrive after the close and it is\nrefused, because by then the outcome is already knowable and accepting it would let a customer\nbuild a flawless \"verified\" track record by submitting yesterday's winners.\n\nDeliberately refuses rather than silently re-timestamping to the next bar: a signal quietly moved\nto a different bar is a different trade, and the customer would never know their intent changed.","operationId":"forward_v1_external_forward__sid__post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForwardIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Forward V1 External Forward  Sid  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["external-signals"],"summary":"Forward Log","description":"The verified forward record: every signal we accepted before its bar closed, SCORED.\n\nComputed on read rather than by a cron. The record is small, it must never be stale when a\ncustomer looks at it, and there is no background job that can fall over silently and leave a\ntear sheet frozen at last week's numbers.","operationId":"forward_log_v1_external_forward__sid__get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Forward Log V1 External Forward  Sid  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/quant/chat":{"post":{"tags":["quant"],"summary":"Chat","operationId":"chat_v1_quant_chat_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Chat V1 Quant Chat Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/insights":{"post":{"tags":["library"],"summary":"Spec Insights","description":"Knowledge-cited insights for an AD-HOC spec (the wizard verdict, before saving).","operationId":"spec_insights_v1_library_insights_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsightsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Spec Insights V1 Library Insights Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library":{"post":{"tags":["library"],"summary":"Save Strategy","operationId":"save_strategy_v1_library_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Save Strategy V1 Library Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["library"],"summary":"List Strategies","description":"The workspace's saved strategies. Optional `project_id` filters to one folder;\n`project_id=root` returns the unfiled strategies (project_id IS NULL).","operationId":"list_strategies_v1_library_get","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Strategies V1 Library Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/{sid}/backtest_code":{"post":{"tags":["library"],"summary":"Backtest Code Strategy","description":"[SPEC 2026-07-28] Re-run a SAVED code strategy — the thing that makes saving one worth doing.\n\nWithout this, a code strategy could be stored and reopened but never re-tested from the library,\nso \"save\" meant \"archive\". It runs in the isolated worker exactly like the wizard's ad-hoc path\n(never in this process — see docs/ISOLATION_DESIGN.md) and returns the SAME result contract as\nthe spec backtest, so one set of components renders both.\n\nDeliberately NOT the reverse of _require_spec: this is the one downstream surface that genuinely\nsupports code, so here a SPEC strategy is what gets refused.","operationId":"backtest_code_strategy_v1_library__sid__backtest_code_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/CodeBacktestIn"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Backtest Code Strategy V1 Library  Sid  Backtest Code Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/starters":{"post":{"tags":["library"],"summary":"Restore Starters","description":"[SPEC 2026-07-28] Put the starter templates for the caller's tier into their library.\n\nStarters are normally seeded at signup and again on a tier change (accounts.seed_starter_library),\nbut a workspace created before that existed — or one where the seeding silently no-opped — has an\nempty library and NO way to get them, because provisioning is idempotent and never runs again.\nThis is that way. Idempotent by name: re-running adds only what's missing, so it can't duplicate.\n\nThese are deliberately vanilla templates to test and modify, NOT a performance claim and NOT the\ndesk's proven strategies.","operationId":"restore_starters_v1_library_starters_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Restore Starters V1 Library Starters Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/{sid}":{"get":{"tags":["library"],"summary":"Get Strategy","operationId":"get_strategy_v1_library__sid__get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Strategy V1 Library  Sid  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["library"],"summary":"Update Strategy","operationId":"update_strategy_v1_library__sid__patch","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__strategies__PatchIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Strategy V1 Library  Sid  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["library"],"summary":"Delete Strategy","operationId":"delete_strategy_v1_library__sid__delete","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Strategy V1 Library  Sid  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/{sid}/insights":{"get":{"tags":["library"],"summary":"Strategy Insights","operationId":"strategy_insights_v1_library__sid__insights_get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Strategy Insights V1 Library  Sid  Insights Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/{sid}/forwardtest":{"post":{"tags":["library"],"summary":"Forward Test","description":"Re-run a saved strategy over the MOST RECENT window (data it was not tuned on) — an honest\nout-of-sample proof before committing real money. This is NOT live paper trading (that is a\nforward-from-deploy engine, a later phase); it is a recent-window backtest, labelled as such.\nFree: deterministic engine compute, no AI, no credits — but quota-capped (429) and subject to\nthe engine's capacity gate (503).","operationId":"forward_test_v1_library__sid__forwardtest_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":60,"title":"Days"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Forward Test V1 Library  Sid  Forwardtest Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/{sid}/paper/deploy":{"post":{"tags":["library"],"summary":"Paper Deploy","description":"Deploy a saved strategy to PAPER — a walk-forward over the trailing window (data it was never\ntuned on), with an equity curve + trade log.\n\n[SPEC 2026-07-28] This used to say \"an ongoing track record ... the record extends over time\".\nIt does not extend, it SLIDES: each refresh re-runs the trailing window and replaces the record,\nso the oldest days fall off as new ones arrive. The response therefore reports `window_days`\n(what was tested), `deployed_days` (how long since you deployed it) and `forward_only` (true only\nonce the tested window lies entirely after the deploy decision) — three checkable numbers instead\nof one flattering label. Nothing here is a live account or a broker connection.\n\nThis is a deterministic, cost-free paper account. It is NOT connected to a live broker and never\nrisks real money — a real-time execution engine is a separate, later phase. Free: no AI, no\ncredits — but quota-capped (429) and subject to the engine's capacity gate (503).","operationId":"paper_deploy_v1_library__sid__paper_deploy_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/PaperIn"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Paper Deploy V1 Library  Sid  Paper Deploy Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/{sid}/paper":{"get":{"tags":["library"],"summary":"Paper Get","operationId":"paper_get_v1_library__sid__paper_get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Paper Get V1 Library  Sid  Paper Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/{sid}/optimize":{"post":{"tags":["library"],"summary":"Optimize Strategy","description":"Search for an OUT-OF-SAMPLE improvement to a saved strategy (structure-only mutations, sealed\n3-way split). Reports the single change that survived — or the honest 'nothing improved it'. Never\ntouches the original; a survivor comes back as a COPY (`best_version_spec`) the customer promotes\nby SAVING it as a new strategy.\n\n[SPEC 2026-07-22] CHARGES CREDITS: a flat compute price (OPTIMIZE_COST_USD through the markup\npipeline) — the variant harness runs hundreds of backtests and is the product's flagship paid\naction. Money path is HOLD -> work -> SETTLE ([SPEC 2026-07-22 scale audit]): a row-locked debit\nat the flat price lands BEFORE the compute (402 naming the shortfall, race-safe), and ANY failed\nrun refunds the hold in full — a 400/503 costs the customer nothing. Ownership is checked before\nmoney: a foreign strategy id stays a 404, never a 402.","operationId":"optimize_strategy_v1_library__sid__optimize_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/OptimizeIn"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Optimize Strategy V1 Library  Sid  Optimize Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["library"],"summary":"Optimize Get","operationId":"optimize_get_v1_library__sid__optimize_get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Optimize Get V1 Library  Sid  Optimize Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/{sid}/rewrite":{"post":{"tags":["library"],"summary":"Rewrite Strategy Route","description":"The AI REWRITE — re-express the customer's strategy through the desk's most relevant VALIDATED\nedge, honoring the trader's optional steering `feedback`, write a new spec, and backtest it. An AI\ncall, so it CHARGES CREDITS — balance is pre-checked against a ceiling before a cent is spent, and\nthe debit is our real metered cost * markup. Never touches the original; the rewrite is a COPY the\ncustomer saves. Honest: if no validated edge maps to the strategy, it 400s WITHOUT spending.","operationId":"rewrite_strategy_route_v1_library__sid__rewrite_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/RewriteIn"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Rewrite Strategy Route V1 Library  Sid  Rewrite Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["library"],"summary":"Rewrite Get","operationId":"rewrite_get_v1_library__sid__rewrite_get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Rewrite Get V1 Library  Sid  Rewrite Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/{sid}/live_readiness":{"get":{"tags":["library"],"summary":"Live Readiness","description":"Has this strategy earned a live deployment? Evidence only, never a prediction.","operationId":"live_readiness_v1_library__sid__live_readiness_get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Live Readiness V1 Library  Sid  Live Readiness Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/{sid}/desk_deploy":{"post":{"tags":["library"],"summary":"Desk Deploy","description":"[SPEC 2026-07-22] \"Evolve & Mutate\": send the saved strategy INTO the trading desk, where it\nregisters exactly like a desk-born strategy — it appears in MY STRATEGIES, paper-trades, and the\nbrain's learning loops (evolution / reconciliation / optimizer / autopilot) start working on it.\n\nUltimate and above (see DESK_TIERS — the desk IS the top tier's product); ownership is checked\nfirst so a foreign id stays a 404 rather than leaking that it exists.\nFree CPU — no AI call, no credit charge. The desk's own /bt_deploy does the registration, so the\nspec lands through the SAME sanitizer every desk strategy passes.","operationId":"desk_deploy_v1_library__sid__desk_deploy_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Desk Deploy V1 Library  Sid  Desk Deploy Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/library/{sid}/crashtest":{"get":{"tags":["library"],"summary":"Crashtest","description":"[SPEC 2026-08-08] Run this strategy through seven named crises.\n\nLABELS, DOES NOT RANK. A crisis window is a handful of trades; ranking on it would be the same\nmultiple-testing mistake the leaderboard refuses. This returns facts per window.\n\nThe engine module owns the three-way outcome (tested / no setup / NO DATA) and the rule that\ncoverage is computed from the BARS. This route owns only the two things it cannot know: how to\nfetch bars for a window, and how to run a spec.","operationId":"crashtest_v1_library__sid__crashtest_get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Crashtest V1 Library  Sid  Crashtest Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/trades/import":{"post":{"tags":["trades"],"summary":"Import Trades","operationId":"import_trades_v1_trades_import_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Import Trades V1 Trades Import Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/trades/template":{"get":{"tags":["trades"],"summary":"Csv Template","operationId":"csv_template_v1_trades_template_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Csv Template V1 Trades Template Get"}}}}}}},"/v1/trades":{"get":{"tags":["trades"],"summary":"List Trades","operationId":"list_trades_v1_trades_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":200,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"market","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Trades V1 Trades Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/trades/imports":{"get":{"tags":["trades"],"summary":"List Imports","operationId":"list_imports_v1_trades_imports_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Imports V1 Trades Imports Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/trades/imports/{imp_id}":{"delete":{"tags":["trades"],"summary":"Delete Import","operationId":"delete_import_v1_trades_imports__imp_id__delete","parameters":[{"name":"imp_id","in":"path","required":true,"schema":{"type":"string","title":"Imp Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Import V1 Trades Imports  Imp Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/trades/analysis":{"get":{"tags":["trades"],"summary":"Analysis","operationId":"analysis_v1_trades_analysis_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Analysis V1 Trades Analysis Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/trades/{tid}/path":{"get":{"tags":["trades"],"summary":"Trade Path","operationId":"trade_path_v1_trades__tid__path_get","parameters":[{"name":"tid","in":"path","required":true,"schema":{"type":"string","title":"Tid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Trade Path V1 Trades  Tid  Path Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/trades/takeaway":{"post":{"tags":["trades"],"summary":"Takeaway","description":"One AI narration of the deterministic analysis. The measurement happened for free before\nthis; what is bought here is the narrative — and every action in it passes the evidence graph,\nso a recommendation our own 87k/530k-sample studies refuted is REMOVED and shown as a removal\nwith the refutation, never delivered as advice. Full refund on any failure.","operationId":"takeaway_v1_trades_takeaway_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Takeaway V1 Trades Takeaway Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/trades/exit-optimizer":{"get":{"tags":["trades"],"summary":"Exit Optimizer","description":"[SPEC 2026-08-08] Re-simulate the customer's own closed trades under alternative exits.\n\nThe engine module (qbt_exitopt) owns the statistics and the refusal; this route owns only the\nthree things it cannot know: which archive market a trade maps to, whether the broker clock was\nverified for that import, and where the M1 bars come from.\n\nTHE CLOCK GATE IS NOT OPTIONAL. Times are stored exactly as the broker printed them while the\narchive is UTC, so an import whose offset was never verified sits on the WRONG BARS — and\n\"your stop would have been hit here\" then describes a different hour of the day. The intratrade\npath route (:330) already refuses to draw for this reason; this refuses to ADVISE for it, which\nmatters more.\n\nBars are M1 where the archive has them, per trade, over the trade's own window plus a tail so a\nlonger holding cap has somewhere to run.","operationId":"exit_optimizer_v1_trades_exit_optimizer_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Exit Optimizer V1 Trades Exit Optimizer Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sync":{"post":{"tags":["sync"],"summary":"Report","description":"The terminal reports in. Closed deals are stored; the position snapshot replaces the last.\n\nReturns what was actually kept — `imported` vs `duplicates` — because an EA that re-sends its\nrecent history every cycle (which is the correct, restart-safe thing for it to do) needs to see\nthat the server is deduping rather than silently accepting.","operationId":"report_v1_sync_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Report V1 Sync Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sync/status":{"get":{"tags":["sync"],"summary":"Account State","description":"Is this account connected, and what is open right now?\n\nTHE FRESHNESS RULE IS THE FEATURE. Three states, and they are not collapsible:\n\n  connected=false          — this account has never reported. Not flat: unknown.\n  connected=true, stale    — it reported once, but not recently enough to believe. Positions\n                             are WITHHELD (`positions: null`) and the age is given, because a\n                             list that may be minutes out of date is worse than no list when\n                             the question is \"am I exposed?\".\n  connected=true, fresh    — the snapshot stands, and `positions: []` genuinely means flat.\n\nEvery response carries `age_s` and `last_seen`, so a caller that ignores `stale` still cannot\nclaim it was not told.","operationId":"account_state_v1_sync_status_get","parameters":[{"name":"account_label","in":"query","required":false,"schema":{"type":"string","default":"default","title":"Account Label"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Account State V1 Sync Status Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sync/accounts":{"get":{"tags":["sync"],"summary":"List Accounts","description":"Every account that has ever reported, newest contact first — the connection list behind the\nUI. Carries the same freshness verdict per row rather than raw timestamps for the client to\nre-derive: one rule, computed once, so no surface can disagree about what \"connected\" means.","operationId":"list_accounts_v1_sync_accounts_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Accounts V1 Sync Accounts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sync/reporter.mq5":{"get":{"tags":["sync"],"summary":"Download Reporter","description":"The reporter EA, with this deployment's API base and the customer's chosen label baked in.\n\nSHIPPED AS SOURCE for the same reason the executor is: the customer can read every line that\ntouches their terminal before they attach it, and see for themselves that there is no\nOrderSend in the file. The API key is NOT baked in — it stays an input they paste on their own\nmachine, so a downloaded file that leaks is not a credential that leaks.","operationId":"download_reporter_v1_sync_reporter_mq5_get","parameters":[{"name":"account_label","in":"query","required":false,"schema":{"type":"string","default":"default","title":"Account Label"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sync/accounts/{account_label}":{"delete":{"tags":["sync"],"summary":"Forget Account","description":"Drop the live snapshot for an account. The TRADES are untouched — this disconnects a\nterminal from the live view, it does not delete the customer's journal, and conflating those\ntwo would make 'stop showing me this stale account' destroy their history.","operationId":"forget_account_v1_sync_accounts__account_label__delete","parameters":[{"name":"account_label","in":"path","required":true,"schema":{"type":"string","title":"Account Label"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Forget Account V1 Sync Accounts  Account Label  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/prop/presets":{"get":{"tags":["prop"],"summary":"Presets","description":"Rulebook SHAPES, in percent of account size. Unbranded on purpose — see the module docstring.\n\nCarries no tenant data, but stays authenticated like every other endpoint: an unauthenticated\nsurface should never appear in this API by omission.","operationId":"presets_v1_prop_presets_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Presets V1 Prop Presets Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/prop":{"get":{"tags":["prop"],"summary":"List Accounts","operationId":"list_accounts_v1_prop_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Accounts V1 Prop Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["prop"],"summary":"Create Account","operationId":"create_account_v1_prop_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Account V1 Prop Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/prop/{acct_id}":{"put":{"tags":["prop"],"summary":"Update Account","operationId":"update_account_v1_prop__acct_id__put","parameters":[{"name":"acct_id","in":"path","required":true,"schema":{"type":"string","title":"Acct Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Account V1 Prop  Acct Id  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["prop"],"summary":"Delete Account","operationId":"delete_account_v1_prop__acct_id__delete","parameters":[{"name":"acct_id","in":"path","required":true,"schema":{"type":"string","title":"Acct Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Account V1 Prop  Acct Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/prop/{acct_id}/status":{"get":{"tags":["prop"],"summary":"Account Status","description":"Where this account stands against its rules, from its OWN imported trades.\n\nOnly trades whose `account_label` matches are considered — a customer running three evaluations\nkeeps three books, and mixing them would produce a number that describes nothing.","operationId":"account_status_v1_prop__acct_id__status_get","parameters":[{"name":"acct_id","in":"path","required":true,"schema":{"type":"string","title":"Acct Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Account Status V1 Prop  Acct Id  Status Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/prop/{acct_id}/simulate":{"post":{"tags":["prop"],"summary":"Simulate","description":"Would this STRATEGY have survived this account's rulebook?\n\nSame evaluator, same limits, same day arithmetic as the real-trades view — only the trade source\nchanges. `backtest` re-runs the strategy over history (metered, like every other backtest);\n`paper` reads the forward record it already has.\n\nWhat this is NOT, stated here because the UI must repeat it: a backtest surviving a rulebook is\nnot a prediction that the account will pass. It is the same history everyone else's marketing\ncalls a guarantee, run against limits that only ever bite in real time. Nothing is projected\nforward, exactly as in `account_status`.","operationId":"simulate_v1_prop__acct_id__simulate_post","parameters":[{"name":"acct_id","in":"path","required":true,"schema":{"type":"string","title":"Acct Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimulateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Simulate V1 Prop  Acct Id  Simulate Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay":{"post":{"tags":["replay"],"summary":"Create","operationId":"create_v1_replay_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__replay__CreateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create V1 Replay Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["replay"],"summary":"List Sessions","operationId":"list_sessions_v1_replay_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Sessions V1 Replay Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/{sid}":{"get":{"tags":["replay"],"summary":"Get Session","operationId":"get_session_v1_replay__sid__get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Session V1 Replay  Sid  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/{sid}/step":{"post":{"tags":["replay"],"summary":"Step","operationId":"step_v1_replay__sid__step_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Step V1 Replay  Sid  Step Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/{sid}/order":{"post":{"tags":["replay"],"summary":"Order","operationId":"order_v1_replay__sid__order_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Order V1 Replay  Sid  Order Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/{sid}/verdict":{"get":{"tags":["replay"],"summary":"Verdict","description":"L2 grading — docs/REPLAY_PLAN.md §4. Returns aggregates only, never bars, and grades a\ndecision ONLY once its full horizon is behind the cursor: scoring an open window would leak\nthe future through the number, so the anti-peek rule applies to the verdict itself.","operationId":"verdict_v1_replay__sid__verdict_get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Verdict V1 Replay  Sid  Verdict Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/{sid}/signal":{"post":{"tags":["replay"],"summary":"Signal","description":"SHADOW MODE — what would YOUR strategy do here?\n\n[SPEC 2026-08-05] Replay could only be traded by hand. `infer` runs the other direction (it\nmines rules FROM your trades), so a strategy you had already built could not be brought into a\nsession at all — the gap the owner named before release.\n\nThis answers one question per bar and takes no action: armed or not, and at what stop and\ntarget. You still place the orders. That is what makes the session worth anything — the verdict\ncan then compare your judgement against your rules on bars neither of you had seen.\n\nFree, like every other step in this module: no AI, no credits.","operationId":"signal_v1_replay__sid__signal_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__replay__SignalIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Signal V1 Replay  Sid  Signal Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/{sid}/auto":{"post":{"tags":["replay"],"summary":"Auto","description":"AUTO MODE — let the strategy place the orders as bars advance.\n\n[SPEC 2026-08-05] The second half of the replay gap. Shadow mode shows you where your strategy\nwould fire; this lets it act, so you can watch it trade bar by bar instead of reading a summary.\n\nThe order it places is the SAME record a hand order writes into `pending` — so it fills at the\nnext bar's open, pays the same costs, is sized by the same equity·risk%/stop-distance, and a\ntwo-sided bar is settled by the same sub-bar ladder. Nothing about the fill is new; the only\nthing that changed is who decided.\n\nNOT A VALIDATION, and the verdict says so. Stepping even the 500-bar maximum yields a handful\nof trades — that is a demonstration you can watch, not evidence a strategy works. The backtester\nis what answers that question, over a decade and with an out-of-sample split. Presenting a\nthree-trade replay as proof would be the exact over-claim this product exists to refuse.","operationId":"auto_v1_replay__sid__auto_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Auto V1 Replay  Sid  Auto Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/{sid}/infer":{"post":{"tags":["replay"],"summary":"Infer","description":"L3 — docs/REPLAY_PLAN.md §5. Mines the rules, backtests them over the decade, and presents\nthe comparison honestly, INCLUDING the uncomfortable outcomes: \"no rule separates your entries\nfrom ordinary bars\" and \"the rules alone beat you\" are both findings, not failures. The decade\nrun goes through meter.check like every other backtest — mining is free, CPU decades are not.\nThe mined spec uses the SAME exit ladder the grader uses (1 ATR stop, 1 ATR target) so its\nexpectancy and your hand verdict's are the same unit. Returns aggregates and the spec — never\nbars, and mining reads nothing past the cursor.","operationId":"infer_v1_replay__sid__infer_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Infer V1 Replay  Sid  Infer Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/{sid}/close":{"post":{"tags":["replay"],"summary":"Close","operationId":"close_v1_replay__sid__close_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloseIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Close V1 Replay  Sid  Close Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/{sid}/modes":{"get":{"tags":["replay"],"summary":"Replay Modes","description":"[SPEC 2026-08-08] Evaluate the SAME mode lenses the backtester runs, at this session's cursor.\n\nA trainee practising \"I only take entries after a liquidity sweep\" can see whether that condition\nis true on the bar in front of them — and it is the same predicate string the backtest gates on,\nso a mode cannot mean one thing in testing and another in training.\n\nANTI-PEEK, twice over. The window ends at cursor_t like every other route here, and\nqbt_replaymodes slices to the cursor again before evaluating. Belt and braces on purpose: this\nmodule's own header calls anti-peek structural, and the one place it would be easiest to lose is\na helper that quietly takes an index into a longer array.\n\nTHE PRE-FED RULE. `regime=exam` returns the armed list with every truth value withheld, so the\ntrainee can see WHICH modes they are being tested on without being told the answer. A mode that\nis shown is never graded; that split is enforced in the engine module, not here.","operationId":"replay_modes_v1_replay__sid__modes_get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"regime","in":"query","required":false,"schema":{"type":"string","default":"coach","title":"Regime"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Replay Modes V1 Replay  Sid  Modes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/{sid}/modes/next":{"get":{"tags":["replay"],"summary":"Replay Modes Next","description":"Smart navigation: the next bar AFTER the cursor where `lens` is true.\n\nCOACH ONLY, AND THE REFUSAL IS THE POINT. Jumping to \"the next liquidity sweep\" tells the trainee\na sweep is there — in an exam that is the answer to the question being asked. The engine's\nnext_where takes no regime argument precisely so this cannot be fudged; the gate lives here,\nwhere the session's own regime is known.\n\nThis necessarily reads bars past the cursor to FIND the target. That is legitimate — the trainee\nis choosing to advance time, exactly as pressing step repeatedly would — but each candidate is\nevaluated on its own slice, so what they see on arrival is what they would have seen stepping\nthere one bar at a time.","operationId":"replay_modes_next_v1_replay__sid__modes_next_get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"lens","in":"query","required":true,"schema":{"type":"string","title":"Lens"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Replay Modes Next V1 Replay  Sid  Modes Next Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/{sid}/regime":{"post":{"tags":["replay"],"summary":"Set Regime","description":"Switch this session between coach and exam.\n\n[SPEC 2026-08-08] ONE-WAY WHILE A SESSION IS LIVE, and that is the whole point. Coach -> exam is\nalways allowed: giving up the hints mid-session costs the trainee nothing but difficulty. Exam ->\ncoach is REFUSED on an active session, because the exam grades SPOTTING — a trainee who could\nflip to coach, read which modes are live, and flip back would be graded on a label we handed\nover. That is the pre-fed rule, and a toggle is exactly how it would be lost.\n\nEnd the session and start a new one to go back to coaching. The refusal names that, so it reads\nas a rule rather than a bug.","operationId":"set_regime_v1_replay__sid__regime_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegimeIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Set Regime V1 Replay  Sid  Regime Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/calibration/me":{"get":{"tags":["replay"],"summary":"My Calibration","description":"Do this trader's high-conviction setups actually do better than their low-conviction ones?\n\n[SPEC 2026-08-08] Every row was rated BEFORE its outcome existed — the rating is written when\nthe order is placed and the outcome is filled in when the position closes, so this measures\njudgement rather than memory. That is the only reason the number means anything; a retro-rated\nhistory always looks beautifully calibrated.\n\nUnsettled ratings are excluded rather than counted as zero: an open trade has no outcome, and a\nzero would enter the correlation as a real result and drag rho toward nothing.","operationId":"my_calibration_v1_replay_calibration_me_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response My Calibration V1 Replay Calibration Me Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/{sid}/pane":{"get":{"tags":["replay"],"summary":"Pane","description":"One extra chart, frozen at the same moment as the session.\n\n[SPEC 2026-08-09] Gap 5(b): up to ten charts advancing together, the way a simulator does. Any\nmarket and any offered timeframe — watching the H4 while you trade the M15, or GBP/USD while you\ntrade EUR/USD, is most of why traders keep several charts open at all.\n\nThe pane carries no orders and no positions. It is somewhere to LOOK, and everything that can be\nacted on stays on the session's own chart, so there is never a question about which chart a\nclick belongs to.\n\nServed per pane rather than as a batch: a market with no history for one pane must not empty the\nother nine, and one 422 should name the pane that caused it.","operationId":"pane_v1_replay__sid__pane_get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"market","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":40,"title":"Market"}},{"name":"tf","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":8,"title":"Tf"}},{"name":"bars","in":"query","required":false,"schema":{"type":"integer","maximum":400,"minimum":20,"default":200,"title":"Bars"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Pane V1 Replay  Sid  Pane Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/corpus/summary":{"get":{"tags":["corpus"],"summary":"Summary","description":"What this workspace has accumulated. Free — it is their own data.","operationId":"summary_v1_corpus_summary_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Summary V1 Corpus Summary Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/corpus/export":{"get":{"tags":["corpus"],"summary":"Export","description":"Hand back the rows themselves — the customer's own labelled data, newest first.\n\nDeliberately the stored rows and not a derived summary: this exists so they can train on it,\nand a dataset you cannot get out of the product is not a dataset.","operationId":"export_v1_corpus_export_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50000,"minimum":1,"default":5000,"title":"Limit"}},{"name":"market","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market"}},{"name":"label","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Export V1 Corpus Export Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/projects":{"get":{"tags":["projects"],"summary":"List Tree","description":"The workspace tree the caller may SEE: every folder they have access to (restricted folders they\naren't shared on — and those folders' subtrees — are omitted) + a per-folder strategy count. The\nclient assembles the nesting from parent_id.","operationId":"list_tree_v1_projects_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Tree V1 Projects Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["projects"],"summary":"Create Project","operationId":"create_project_v1_projects_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__projects__CreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Project V1 Projects Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/projects/{pid}":{"get":{"tags":["projects"],"summary":"Get Project","description":"One folder — 404 if it doesn't exist OR the caller can't see it (a restricted folder must be\nindistinguishable from a missing one).","operationId":"get_project_v1_projects__pid__get","parameters":[{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Project V1 Projects  Pid  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["projects"],"summary":"Update Project","operationId":"update_project_v1_projects__pid__patch","parameters":[{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__projects__PatchIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Project V1 Projects  Pid  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["projects"],"summary":"Delete Project","description":"Delete a folder. Its direct child folders re-parent to root and its strategies become\nunfiled — data is never orphaned or deleted with the folder. (ondelete=SET NULL handles the\nFK; we set parent explicitly so nested folders don't vanish from the tree.)","operationId":"delete_project_v1_projects__pid__delete","parameters":[{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Project V1 Projects  Pid  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/projects/{pid}/shares":{"get":{"tags":["projects"],"summary":"List Shares","description":"The folder's sharing state — who has access and at what level. Only someone who can WRITE the\nfolder (editor / admin / owner) may see or manage its sharing.","operationId":"list_shares_v1_projects__pid__shares_get","parameters":[{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Shares V1 Projects  Pid  Shares Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["projects"],"summary":"Upsert Share","description":"Grant (or change) a teammate's access to this folder. The first share flips the folder to\n'restricted' automatically; the caller is auto-kept as editor so they never lock themselves out.","operationId":"upsert_share_v1_projects__pid__shares_put","parameters":[{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Upsert Share V1 Projects  Pid  Shares Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/projects/{pid}/shares/{user_id}":{"delete":{"tags":["projects"],"summary":"Remove Share","operationId":"remove_share_v1_projects__pid__shares__user_id__delete","parameters":[{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Remove Share V1 Projects  Pid  Shares  User Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/projects/{pid}/visibility":{"patch":{"tags":["projects"],"summary":"Set Visibility","description":"Restrict a folder (private to its shared members + admins) or open it back to the whole\nworkspace. Restricting keeps the caller as editor so they never lose their own folder.","operationId":"set_visibility_v1_projects__pid__visibility_patch","parameters":[{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisibilityIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Set Visibility V1 Projects  Pid  Visibility Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/members":{"get":{"tags":["members"],"summary":"List Members","description":"Everyone in the current workspace. Any member can see the roster; only the caller's own row is\nflagged `is_you`, and management actions are gated separately.","operationId":"list_members_v1_members_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Members V1 Members Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/members/workspaces":{"get":{"tags":["members"],"summary":"My Workspaces","description":"Every workspace the signed-in user belongs to — powers the workspace switcher. The `active` one\nis whichever the current request resolved to (token ws or the X-Workspace-Id override).","operationId":"my_workspaces_v1_members_workspaces_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response My Workspaces V1 Members Workspaces Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/members/invites":{"post":{"tags":["members"],"summary":"Create Invite","operationId":"create_invite_v1_members_invites_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Invite V1 Members Invites Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["members"],"summary":"List Invites","operationId":"list_invites_v1_members_invites_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Invites V1 Members Invites Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/members/invites/{invite_id}":{"delete":{"tags":["members"],"summary":"Revoke Invite","operationId":"revoke_invite_v1_members_invites__invite_id__delete","parameters":[{"name":"invite_id","in":"path","required":true,"schema":{"type":"string","title":"Invite Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revoke Invite V1 Members Invites  Invite Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/members/invites/accept":{"post":{"tags":["members"],"summary":"Accept Invite","description":"Redeem an invite code -> join its workspace with the granted role. Idempotent: an existing member\nkeeps their current role (an invite never silently downgrades). Any signed-in user may accept a\nvalid code — the code IS the authorization.","operationId":"accept_invite_v1_members_invites_accept_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Accept Invite V1 Members Invites Accept Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/members/{user_id}":{"patch":{"tags":["members"],"summary":"Set Member Role","operationId":"set_member_role_v1_members__user_id__patch","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Set Member Role V1 Members  User Id  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["members"],"summary":"Remove Member","operationId":"remove_member_v1_members__user_id__delete","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Remove Member V1 Members  User Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/desk/endpoint":{"get":{"tags":["deskbridge"],"summary":"Desk Endpoint","description":"[SPEC 2026-07-27] WHERE is THIS customer's desk? The web app calls this to route the SSO\nhandoff, instead of reading one global NEXT_PUBLIC_DESK_URL. Entitlement is enforced HERE\n(server-side) — the sidebar only hides the link; this is a real door.\n\nReturns {status, desk_url?}:\n  locked        — not entitled (below Ultimate/trader); web bounces to pricing.\n  insufficient_credits — entitled but below the launch floor; carries {balance, required} (the\n                  same field NAMES every other 402 in this product uses) so the web can send\n                  them to a top-up instead of into a desk that would refuse every click.\n  ready         — desk_url is browser-reachable; web mints the JWT and redirects there.\n  provisioning  — a per-tenant desk is being stood up (P2); web shows \"setting up…\".\n  error/suspended/deprovisioned — honest states for a per-tenant desk (P2).\n  unconfigured  — entitled but no desk exists AND no browser-reachable shared one either;\n                  carries `detail` saying which knob is missing (operator gap, not a dead link).\n\nP1: no per-tenant rows exist yet, so an entitled workspace falls back to the single shared\npublic desk — QP_DESK_PUBLIC_URL when set, otherwise the deploy target QP_DESK_URL *only* if it\nis verifiably public (see _shared_desk_for_browser / _browser_reachable).","operationId":"desk_endpoint_v1_desk_endpoint_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Desk Endpoint V1 Desk Endpoint Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/evolved":{"get":{"tags":["deskbridge"],"summary":"Evolved","description":"The customer's evolution feed. Winners carry the exact improvement story: which strategy,\nwhich lens/filter combination won, sealed-OOS R before vs after, and the deployed paper copy.","operationId":"evolved_v1_evolved_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Evolved V1 Evolved Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/evolved/{cid}/promote":{"post":{"tags":["deskbridge"],"summary":"Promote Evolved","description":"[SPEC 2026-08-06] THE RETURN LEG. Copy a sealed winner's spec into the customer's library.\n\nUntil now the loop ran one way. The desk swept, found an improvement, applied the winning lenses\nand deployed the result as a paper challenger — and there it stayed. `api/deskbridge.evolved()`\nrebuilt each winner row out of METRICS ALONE, so from the app a customer could export only the\nORIGINAL strategy, never the better one the Conscious found for them. Five surfaces promised\notherwise; on 2026-08-06 the promise was deleted rather than kept, because nothing came back.\nThis route is what makes it come back.\n\nWHAT LANDS: a NEW strategy, never an overwrite. The house rule is optimise COPIES, never\noriginals ([[strategy-optimizer-copies]]) — a customer who dislikes the evolved version must\nstill have the one they wrote. Both rows sit in the library and they choose.\n\nTHE EVIDENCE TRAVELS WITH IT. before/after sealed R, the winning lens combination, how many lens\ncombinations were tried, how many sealed trades confirmed it, and the caveat — all stamped onto\nthe copy. A bare \"+0.43R\" invites promoting a best-of-31 on six trades into live trading; the\nsame delta beside \"best of 31, 6 sealed trades, provisional\" invites waiting. Same number,\nopposite decision. That is why the desk attaches the qualifier, and dropping it here would\nreintroduce the exact defect the desk-side spec exists to prevent.\n\nNOTHING IS ARMED. This writes a library row. It does not touch the challenger (which keeps\npaper-trading), does not touch the original, and cannot start live trading — live stays behind\nthe customer's own explicit arming on their own terminal.","operationId":"promote_evolved_v1_evolved__cid__promote_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Promote Evolved V1 Evolved  Cid  Promote Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/evolved/{cid}/export":{"post":{"tags":["deskbridge"],"summary":"Export Evolved","description":"[SPEC 2026-08-06] Export a sealed winner's code WITHOUT saving it first.\n\nThe library's export works off the spec the row already carries. An evolved winner has no such\nrow — its spec lives on the desk as the paper challenger — so this fetches it and exports in one\ncall. Same generator as /v1/wizard/export, same tier wall, same refusals; only the source of the\nspec differs.\n\nDeliberately separate from promote: a customer who wants the MQL5 file should not have to save a\nstrategy they may not keep. Promote persists, this does not — nothing is written by this route.","operationId":"export_evolved_v1_evolved__cid__export_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvolvedExportIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Export Evolved V1 Evolved  Cid  Export Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/mt5":{"get":{"tags":["deskbridge"],"summary":"Mt5 Status","operationId":"mt5_status_v1_mt5_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Mt5 Status V1 Mt5 Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/mt5/connect":{"post":{"tags":["deskbridge"],"summary":"Mt5 Connect","operationId":"mt5_connect_v1_mt5_connect_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MT5ConnectIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Mt5 Connect V1 Mt5 Connect Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/mt5/disconnect":{"post":{"tags":["deskbridge"],"summary":"Mt5 Disconnect","operationId":"mt5_disconnect_v1_mt5_disconnect_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Mt5 Disconnect V1 Mt5 Disconnect Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/desk/paper":{"get":{"tags":["deskbridge"],"summary":"Paper Book","description":"The desk's paper book, read server-to-server and rendered inside the app.\n\nWHY THIS EXISTS. The paper book is the end of the loop the wizard starts: describe a strategy,\nbacktest it, deploy it — and then, until now, leave the app entirely to find out whether it\never traded. This closes it in place.\n\nWHAT IT IS NOT. This is the SHARED desk's book (P1 routing: one desk serves every entitled\ntenant, see docs/PER_TENANT_DESK_DESIGN.md), so it is the platform's paper account and NOT a\nprivate per-customer one. The UI says so in those words. Calling it \"your paper account\" would\nbe the kind of small lie that costs all the trust the rest of the product buys — and the\nmoment DeskInstance routing lands (P2) this same route starts returning a genuinely private\nbook with no change here.\n\nRead-only and free: no orders, no cancels, no toggles. The desk owns execution; the app owns\nthe window onto it. Positions are already priced by the desk against live mid, so nothing is\nrecomputed here — a second opinion on floating P&L is a second answer, and two answers about\nmoney is one too many.","operationId":"paper_book_v1_desk_paper_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Paper Book V1 Desk Paper Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/settings/profile":{"get":{"tags":["settings"],"summary":"Profile","operationId":"profile_v1_settings_profile_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Profile V1 Settings Profile Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["settings"],"summary":"Update Profile","operationId":"update_profile_v1_settings_profile_patch","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Profile V1 Settings Profile Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/settings/password":{"post":{"tags":["settings"],"summary":"Change Password","operationId":"change_password_v1_settings_password_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Change Password V1 Settings Password Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/settings/workspace":{"patch":{"tags":["settings"],"summary":"Rename Workspace","operationId":"rename_workspace_v1_settings_workspace_patch","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Rename Workspace V1 Settings Workspace Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/mobile/auth/google":{"post":{"tags":["mobile-auth"],"summary":"Google","description":"A Google ID token from the app's native OAuth flow -> our session token.","operationId":"google_v1_mobile_auth_google_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderTokenIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Google V1 Mobile Auth Google Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/mobile/auth/apple":{"post":{"tags":["mobile-auth"],"summary":"Apple","description":"Sign in with Apple. NOT optional on iOS: Apple requires it wherever a third-party social\nlogin is offered, so shipping Google alone on iOS fails review.","operationId":"apple_v1_mobile_auth_apple_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderTokenIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Apple V1 Mobile Auth Apple Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/mobile/auth/refresh":{"post":{"tags":["mobile-auth"],"summary":"Refresh","description":"Trade an aging session token for a fresh one, without a trip back through Google.\n\nTHE TRADE, stated plainly. Accepting a recently-expired token as proof of a live session is\nweaker than a separate revocable refresh token — a stolen token stays usable for the grace\nwindow. It is chosen over the alternative actually on the table, which was raising\nQP_JWT_TTL_MIN so a phone stays signed in: a long-lived access token is worse in the same way\nAND cannot be revoked at all, because nothing re-reads the database until it expires. This path\nre-checks `disabled` and the membership on EVERY refresh, so a suspended account loses access at\nthe next refresh instead of whenever its token happened to run out.\n\nWHAT ACTUALLY BOUNDS THE EXPOSURE is that re-check — NOT the grace window, which an earlier\nversion of this docstring claimed. Refreshes chain: each one mints a fresh expiry, so a stolen\ntoken stays renewable for as long as the attacker keeps refreshing, indefinitely, until the\naccount is disabled or the membership is removed. QP_MOBILE_REFRESH_GRACE_DAYS bounds something\nnarrower: how long an app may sit UNOPENED before its user has to sign in again. An absolute cap\non session age would bound the theft window properly; it is deliberately not implemented here\nbecause it signs every honest user out on a schedule, which is a product decision, not a\nrefactor.","operationId":"refresh_v1_mobile_auth_refresh_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Refresh V1 Mobile Auth Refresh Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/signals/{sid}":{"post":{"tags":["signals"],"summary":"Get Signal","description":"The decision at the last closed bar — computed by the same engine the backtest ran.","operationId":"get_signal_v1_signals__sid__post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__signals__SignalIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Signal V1 Signals  Sid  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/signals/{sid}/client":{"get":{"tags":["signals"],"summary":"Download Client","description":"The thin client, personalised with the strategy id. Safe to share — it holds no logic and\nno credentials (the key comes from the user's own environment).","operationId":"download_client_v1_signals__sid__client_get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/signals/{sid}/bundle":{"get":{"tags":["signals"],"summary":"Download Bundle","description":"The self-contained engine bundle — only when the OWNER has flipped `export.full_code` to 1.\nShips the REAL qbt_engine + this strategy's spec + a runner calling run_spec(), so the shipped\ncode executes exactly as backtested (the same sealed entry point test_export_parity proves).","operationId":"download_bundle_v1_signals__sid__bundle_get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deployments":{"post":{"tags":["deployments"],"summary":"Start","description":"Start a deployment. Refuses only on things that make the deployment MEANINGLESS — a strategy\nthat is not yours, an instrument we cannot load, a live start on an unpaid plan. Everything\nelse is a warning.","operationId":"start_v1_deployments_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Start V1 Deployments Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["deployments"],"summary":"List Deployments","description":"The panel's listing. Deliberately WITHOUT the per-deployment record: computing one backtest\nper row would make a page with twelve deployments twelve engine runs deep, and the list is what\nloads first. The record is one click away on the detail route, where it is asked for.","operationId":"list_deployments_v1_deployments_get","parameters":[{"name":"include_stopped","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Include Stopped"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Deployments V1 Deployments Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deployments/{did}/stop":{"post":{"tags":["deployments"],"summary":"Stop","description":"THE KILL SWITCH. Idempotent — a second press is a no-op, not a 409, because the one moment a\ncustomer presses this twice is the moment they are least willing to read an error.\n\nStopping does not delete the record. The point of running a strategy forward is the history it\nleaves, and a kill switch that erased it would make people hesitate before using it.","operationId":"stop_v1_deployments__did__stop_post","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"string","title":"Did"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/StopIn"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Stop V1 Deployments  Did  Stop Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deployments/{did}":{"get":{"tags":["deployments"],"summary":"Detail","description":"One deployment, with the record computed fresh. Never cached — a stale forward record is the\none number on this platform that must not be allowed to lie by being old.","operationId":"detail_v1_deployments__did__get","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"string","title":"Did"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Detail V1 Deployments  Did  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deployments/{did}/poll":{"get":{"tags":["deployments"],"summary":"Poll","description":"THE EXECUTOR'S PULL. Returns the decision at the last closed bar — or `halted`.\n\n`halted` is checked FIRST and returns no signal at all, not a signal the client is asked to\nignore. An executor that receives a decision alongside a flag has to be trusted to honour the\nflag; an executor that receives no decision has nothing to act on. That difference is the kill\nswitch actually working.\n\nThe bars come from OUR archive rather than from the caller (that is what /v1/signals is for,\nwhere the customer supplies the tape). Here the deployment already names the instrument, so\nasking the executor to ship 300 bars back to us would be pure ceremony — and would let a caller\nchoose which history their own signal was computed on.","operationId":"poll_v1_deployments__did__poll_get","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"string","title":"Did"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Poll V1 Deployments  Did  Poll Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deployments/{did}/fill":{"post":{"tags":["deployments"],"summary":"Report Fill","description":"The executor reports back. Accepted on a STOPPED deployment on purpose: the exit that closes\na position after the kill switch is exactly the fill you most want on the record, and refusing\nit would leave every halted deployment showing a position that never closed.\n\nIdempotent per (t, kind, side): a retried POST must not double-count a fill into the record.","operationId":"report_fill_v1_deployments__did__fill_post","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"string","title":"Did"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FillIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Report Fill V1 Deployments  Did  Fill Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deployments/{did}/ea":{"get":{"tags":["deployments"],"summary":"Download Ea","description":"The MetaTrader 5 Expert Advisor for this deployment — the sealed executor.\n\nWHY AN EA RATHER THAN TRANSLATED CODE. This file executes; it does not decide. It asks us for\nthe decision at each closed bar and places the order on the customer's own broker. That is what\nmakes it work for EVERY strategy: the sweep/level/structure primitives in\nqbt_export.MQL_UNSUPPORTED_STRUCTURE have no MetaTrader equivalent and cannot be translated —\nbut they never need to be, because the engine that understands them stays on our side.\n\nIT CARRIES NO CREDENTIAL. The API key is an input the customer fills in on their own terminal,\nand their broker password is never involved at all — the EA runs inside a terminal that is\nalready logged in. We hold nothing.\n\nLIVE MODE ONLY, for the same reason the reference executor is: a paper deployment is simulated\nby us, so there is no signal for an EA to act on and shipping one would invite a customer to\nattach it and wait for fills that can never come.","operationId":"download_ea_v1_deployments__did__ea_get","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"string","title":"Did"}},{"name":"mode","in":"query","required":false,"schema":{"type":"string","default":"sealed","title":"Mode"}},{"name":"accept_approximation","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Accept Approximation"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/deployments/{did}/client":{"get":{"tags":["deployments"],"summary":"Download Executor","description":"The reference executor, personalised with this deployment's id, market and bar length.\n\nSHIPPED AS SOURCE, not a binary or a hosted agent, and that is the point: the customer must be\nable to read every line that sits between our signal and their money. It holds no credentials\n(the key comes from their own environment) and no strategy logic (that stays on our servers).","operationId":"download_executor_v1_deployments__did__client_get","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"string","title":"Did"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/institutional/access":{"get":{"tags":["institutional"],"summary":"Access","description":"Does this caller's tier include institutional validation? Lets the UI render the paywall\nwithout guessing, while the server stays the authority.","operationId":"access_v1_institutional_access_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Access V1 Institutional Access Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/institutional/validate":{"post":{"tags":["institutional"],"summary":"Validate","description":"The full institutional tear-sheet for one strategy on one market. Desk tier only, quota-capped.","operationId":"validate_v1_institutional_validate_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Validate V1 Institutional Validate Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/institutional/optimize":{"post":{"tags":["institutional"],"summary":"Optimize","description":"Train the engine on the desk's OWN strategy: try the catalogued changes and keep only what\nsurvives a three-way sealed split. Returns the winning variant + before->after, or the honest\n'nothing here improves it out of sample'. Desk tier only, quota-capped.","operationId":"optimize_v1_institutional_optimize_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Optimize V1 Institutional Optimize Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/keys":{"post":{"tags":["keys"],"summary":"Create Key","description":"Mint a key. The plaintext is in this response and NOWHERE else, ever again.","operationId":"create_key_v1_keys_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Key V1 Keys Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["keys"],"summary":"List Keys","operationId":"list_keys_v1_keys_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Keys V1 Keys Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/keys/{key_id}/revoke":{"post":{"tags":["keys"],"summary":"Revoke Key","operationId":"revoke_key_v1_keys__key_id__revoke_post","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revoke Key V1 Keys  Key Id  Revoke Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/paradox":{"get":{"tags":["catalog"],"summary":"Paradox","description":"The proven strategy library. The surface is public (anonymous == free, teased); ACCESS is a\nserver-side kill switch (QP_PARADOX_RELEASED) held shut until each strategy clears the same\nout-of-sample bar we hold customers to. So the page can ship without releasing the strategies.","operationId":"paradox_v1_paradox_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-workspace-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Workspace-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Paradox V1 Paradox Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/affiliates/apply":{"post":{"tags":["affiliates"],"summary":"Apply","operationId":"apply_v1_affiliates_apply_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Apply V1 Affiliates Apply Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/affiliates/login":{"post":{"tags":["affiliates"],"summary":"Login","operationId":"login_v1_affiliates_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Login V1 Affiliates Login Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/affiliates/logout":{"post":{"tags":["affiliates"],"summary":"Logout","operationId":"logout_v1_affiliates_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Logout V1 Affiliates Logout Post"}}}}}}},"/v1/affiliates/me":{"get":{"tags":["affiliates"],"summary":"Me","operationId":"me_v1_affiliates_me_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"qp_aff","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qp Aff"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Me V1 Affiliates Me Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/affiliates/commissions":{"get":{"tags":["affiliates"],"summary":"Commissions","operationId":"commissions_v1_affiliates_commissions_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"qp_aff","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qp Aff"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Commissions V1 Affiliates Commissions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/affiliates/me/connect/onboard":{"post":{"tags":["affiliates"],"summary":"Connect Onboard","description":"[SPEC 2026-08-04] Start (or resume) Stripe onboarding and return a hosted link.\n\nOnly an APPROVED affiliate may onboard. A pending application has no referral code and can earn\nnothing, so creating a connected account for one would leave orphaned Stripe accounts for every\nstranger who signed up — and Express account creation is a real object on the platform, not a\nfree-form draft.\n\nThe link is generated per call and never cached: account links are single-use and expire in\nminutes, so a stored one is a broken one.","operationId":"connect_onboard_v1_affiliates_me_connect_onboard_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"qp_aff","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qp Aff"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Connect Onboard V1 Affiliates Me Connect Onboard Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/affiliates/me/payout":{"patch":{"tags":["affiliates"],"summary":"Set Payout","description":"Affiliates may update where THEY want to be paid at any time — this never touches the\ncommission plan (rate/type), which only staff can set.\n\n[SPEC 2026-08-04] Two fixes, both on the field that decides where money is sent.\n\nPATCH SEMANTICS. This assigned both columns unconditionally, so sending only `payout_details`\nsilently nulled `payout_method` — an affiliate correcting their account number would wipe how\nthey get paid and see a success response. Only fields actually present in the request body are\nwritten now; `model_fields_set` distinguishes \"absent\" from \"explicitly null\", so clearing a\nfield on purpose still works.\n\nAUDIT. A change of payout destination is the single most valuable thing an attacker who takes\nover an affiliate account can do, and it left no trace at all. Every change is now recorded with\nthe before/after and the requesting IP. The details themselves are NOT written to the audit row\n— that log is read by staff and a bank account does not belong in it; the record answers \"who\nchanged it, when, from where\", which is what an investigation needs.","operationId":"set_payout_v1_affiliates_me_payout_patch","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"qp_aff","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qp Aff"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayoutIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Set Payout V1 Affiliates Me Payout Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AcceptIn":{"properties":{"code":{"type":"string","maxLength":64,"minLength":6,"title":"Code"}},"type":"object","required":["code"],"title":"AcceptIn"},"AccountIn":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name"},"account_label":{"type":"string","maxLength":80,"title":"Account Label","default":"default"},"start_balance":{"type":"number","exclusiveMinimum":0.0,"title":"Start Balance"},"currency":{"type":"string","maxLength":8,"title":"Currency","default":"USD"},"phase":{"type":"string","pattern":"^(evaluation|funded)$","title":"Phase","default":"evaluation"},"dd_mode":{"type":"string","pattern":"^(static|trailing)$","title":"Dd Mode","default":"static"},"day_reset_h":{"type":"integer","maximum":23.0,"minimum":0.0,"title":"Day Reset H","default":0},"rules":{"additionalProperties":{"type":"number"},"type":"object","title":"Rules"},"preset_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preset Id"}},"type":"object","required":["name","start_balance"],"title":"AccountIn"},"AlertIn":{"properties":{"strategy_id":{"type":"string","title":"Strategy Id"},"markets":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":12},{"type":"null"}],"title":"Markets"}},"type":"object","required":["strategy_id"],"title":"AlertIn"},"ApplyIn":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"email":{"type":"string","maxLength":320,"minLength":3,"title":"Email"},"password":{"type":"string","maxLength":200,"minLength":1,"title":"Password"},"payout_method":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Payout Method"},"payout_details":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Payout Details"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes"}},"type":"object","required":["name","email","password"],"title":"ApplyIn"},"ApproveIn":{"properties":{"commission_type":{"type":"string","pattern":"^(one_time|recurring)$","title":"Commission Type"},"commission_pct":{"type":"number","maximum":100.0,"exclusiveMinimum":0.0,"title":"Commission Pct"},"spend_pct":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Spend Pct"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["commission_type","commission_pct","reason"],"title":"ApproveIn"},"ApprovePayoutIn":{"properties":{"reason":{"type":"string","title":"Reason"}},"type":"object","required":["reason"],"title":"ApprovePayoutIn"},"AuthorIn":{"properties":{"source":{"type":"string","maxLength":4000,"minLength":1,"title":"Source"},"target":{"type":"string","pattern":"^(auto|spec|code)$","title":"Target","default":"auto"},"job_id":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Job Id"},"kind":{"type":"string","pattern":"^(english|pine|mql|python)$","title":"Kind","default":"english"}},"type":"object","required":["source"],"title":"AuthorIn"},"AutoIn":{"properties":{"strategy_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Strategy Id"}},"type":"object","title":"AutoIn"},"BarIn":{"properties":{"t":{"type":"integer","title":"T"},"o":{"type":"number","title":"O"},"h":{"type":"number","title":"H"},"l":{"type":"number","title":"L"},"c":{"type":"number","title":"C"},"v":{"type":"number","title":"V","default":0.0}},"type":"object","required":["t","o","h","l","c"],"title":"BarIn"},"CancelPayoutIn":{"properties":{"reason":{"type":"string","title":"Reason"}},"type":"object","required":["reason"],"title":"CancelPayoutIn"},"CatalogRow":{"properties":{"id":{"type":"string","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"tier":{"type":"string","title":"Tier"},"source":{"type":"string","title":"Source"},"hook":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hook"},"locked":{"type":"boolean","title":"Locked"},"upgrade_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upgrade To"},"cta":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cta"}},"type":"object","required":["id","tier","source","locked"],"title":"CatalogRow"},"ChartReadIn":{"properties":{"image_b64":{"type":"string","maxLength":7000000,"minLength":32,"title":"Image B64"},"media_type":{"type":"string","pattern":"^image/(png|jpeg|webp|gif)$","title":"Media Type","default":"image/png"}},"type":"object","required":["image_b64"],"title":"ChartReadIn"},"ChatImage":{"properties":{"b64":{"type":"string","maxLength":2700000,"minLength":16,"title":"B64"},"media_type":{"type":"string","pattern":"^image/(png|jpeg|gif|webp)$","title":"Media Type","default":"image/png"}},"type":"object","required":["b64"],"title":"ChatImage"},"ChatIn":{"properties":{"messages":{"items":{"$ref":"#/components/schemas/ChatMsg"},"type":"array","maxItems":24,"minItems":1,"title":"Messages"},"context":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Context"},"allow_write":{"type":"boolean","title":"Allow Write","default":false}},"type":"object","required":["messages"],"title":"ChatIn"},"ChatMsg":{"properties":{"role":{"type":"string","pattern":"^(user|assistant)$","title":"Role"},"content":{"type":"string","maxLength":4000,"title":"Content","default":""},"images":{"anyOf":[{"items":{"$ref":"#/components/schemas/ChatImage"},"type":"array","maxItems":4},{"type":"null"}],"title":"Images"}},"type":"object","required":["role"],"title":"ChatMsg"},"CheckoutIn":{"properties":{"tier":{"type":"string","pattern":"^(pro|trader)$","title":"Tier"},"success_url":{"type":"string","title":"Success Url"},"cancel_url":{"type":"string","title":"Cancel Url"},"interval":{"type":"string","pattern":"^(week|month|year)$","title":"Interval","default":"month"}},"type":"object","required":["tier","success_url","cancel_url"],"title":"CheckoutIn"},"CloseIn":{"properties":{"position_id":{"type":"string","title":"Position Id"}},"type":"object","required":["position_id"],"title":"CloseIn"},"CodeBacktestIn":{"properties":{"market":{"type":"string","maxLength":40,"minLength":1,"title":"Market","default":"BTC"},"tf":{"type":"string","maxLength":8,"title":"Tf","default":"H1"},"days":{"type":"integer","maximum":100000.0,"minimum":30.0,"title":"Days","default":365}},"type":"object","title":"CodeBacktestIn"},"CompareIn":{"properties":{"ids":{"items":{"type":"string"},"type":"array","title":"Ids"}},"type":"object","required":["ids"],"title":"CompareIn"},"ConnectIn":{"properties":{"return_url":{"type":"string","maxLength":500,"minLength":8,"title":"Return Url"},"refresh_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Refresh Url"}},"type":"object","required":["return_url"],"title":"ConnectIn"},"ContentIn":{"properties":{"value":{"type":"string","maxLength":20000,"title":"Value"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["value"],"title":"ContentIn"},"CreditCheckoutIn":{"properties":{"pack":{"type":"string","title":"Pack"},"success_url":{"type":"string","title":"Success Url"},"cancel_url":{"type":"string","title":"Cancel Url"}},"type":"object","required":["pack","success_url","cancel_url"],"title":"CreditCheckoutIn"},"CreditsIn":{"properties":{"credits":{"type":"number","title":"Credits","description":"positive to grant, negative to claw back"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["credits","reason"],"title":"CreditsIn"},"DisableAffiliateIn":{"properties":{"disabled":{"type":"boolean","title":"Disabled"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["disabled","reason"],"title":"DisableAffiliateIn"},"DisableIn":{"properties":{"disabled":{"type":"boolean","title":"Disabled"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["disabled","reason"],"title":"DisableIn"},"EntitlementOut":{"properties":{"workspace_id":{"type":"string","title":"Workspace Id"},"tier":{"type":"string","title":"Tier"},"via":{"type":"string","title":"Via"},"entitled":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Entitled"}},"type":"object","required":["workspace_id","tier","via"],"title":"EntitlementOut"},"EvidenceIn":{"properties":{"spec":{"additionalProperties":true,"type":"object","title":"Spec"},"market":{"type":"string","title":"Market","default":"BTC"},"tf":{"type":"string","title":"Tf","default":"M15"},"days":{"type":"integer","maximum":3700.0,"minimum":30.0,"title":"Days","default":365},"entry_i":{"type":"integer","minimum":1.0,"title":"Entry I"},"exit_i":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Exit I"}},"type":"object","required":["spec","entry_i"],"title":"EvidenceIn"},"EvolvedExportIn":{"properties":{"dialect":{"type":"string","pattern":"^(pine|mql|python|lean|backtrader|vectorbt)$","title":"Dialect","default":"pine"}},"type":"object","title":"EvolvedExportIn"},"ExecutePayoutIn":{"properties":{"adapter":{"type":"string","title":"Adapter","default":"manual"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["reason"],"title":"ExecutePayoutIn"},"ExportIn":{"properties":{"spec":{"additionalProperties":true,"type":"object","title":"Spec"},"dialect":{"type":"string","pattern":"^(pine|mql|python|lean|backtrader|vectorbt)$","title":"Dialect","default":"pine"},"name":{"type":"string","maxLength":80,"title":"Name","default":"My Strategy"}},"type":"object","required":["spec"],"title":"ExportIn"},"FailPayoutIn":{"properties":{"error":{"type":"string","title":"Error"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["error","reason"],"title":"FailPayoutIn"},"FeedbackIn":{"properties":{"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"force":{"type":"boolean","title":"Force","default":false}},"type":"object","title":"FeedbackIn"},"FillIn":{"properties":{"t":{"type":"integer","title":"T","description":"the bar time this fill answers (epoch seconds)"},"side":{"type":"string","pattern":"^(long|short|flat)$","title":"Side"},"price":{"type":"number","exclusiveMinimum":0.0,"title":"Price"},"size":{"type":"number","minimum":0.0,"title":"Size","default":0.0},"kind":{"type":"string","pattern":"^(entry|exit|reject)$","title":"Kind","default":"entry"},"reason":{"type":"string","maxLength":200,"title":"Reason","default":""}},"type":"object","required":["t","side","price"],"title":"FillIn","description":"What the executor actually did. Every field is the EXECUTOR'S truth, never ours."},"ForgotIn":{"properties":{"email":{"type":"string","maxLength":320,"minLength":3,"title":"Email"}},"type":"object","required":["email"],"title":"ForgotIn"},"ForgotOut":{"properties":{"ok":{"type":"boolean","title":"Ok","default":true},"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"ForgotOut"},"ForwardIn":{"properties":{"market":{"type":"string","maxLength":32,"minLength":1,"title":"Market"},"tf":{"type":"string","pattern":"^(M5|M15|M30|H1|H4|D)$","title":"Tf","default":"H1"},"side":{"type":"string","pattern":"^(long|short)$","title":"Side"},"bar_t":{"type":"integer","title":"Bar T","description":"epoch SECONDS of the bar this signal is for (must be OPEN)"},"sl_atr":{"type":"number","maximum":20.0,"exclusiveMinimum":0.0,"title":"Sl Atr","default":1.5},"tp":{"type":"string","maxLength":32,"title":"Tp","default":"atr:2"},"note":{"type":"string","maxLength":200,"title":"Note","default":""}},"type":"object","required":["market","side","bar_t"],"title":"ForwardIn"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ImportIn":{"properties":{"filename":{"type":"string","maxLength":200,"title":"Filename","default":""},"content_b64":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content B64"},"content_gz_b64":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Gz B64"},"rows":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Rows"},"account_label":{"type":"string","maxLength":80,"title":"Account Label","default":"default"}},"type":"object","title":"ImportIn"},"InsightsIn":{"properties":{"spec":{"additionalProperties":true,"type":"object","title":"Spec"}},"type":"object","required":["spec"],"title":"InsightsIn"},"InviteIn":{"properties":{"role":{"type":"string","title":"Role","default":"member"},"email":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Email"},"ttl_hours":{"anyOf":[{"type":"integer","maximum":2160.0,"minimum":1.0},{"type":"null"}],"title":"Ttl Hours"}},"type":"object","title":"InviteIn"},"KeyIn":{"properties":{"name":{"type":"string","maxLength":120,"title":"Name","default":"default"}},"type":"object","title":"KeyIn"},"LeadIn":{"properties":{"kind":{"type":"string","pattern":"^(demo|sales|contact)$","title":"Kind"},"name":{"type":"string","maxLength":160,"minLength":1,"title":"Name"},"email":{"type":"string","maxLength":320,"minLength":3,"title":"Email"},"company":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Company"},"role":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Role"},"desk_type":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"title":"Desk Type"},"message":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Message"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"}},"type":"object","required":["kind","name","email"],"title":"LeadIn"},"LeadPatch":{"properties":{"status":{"type":"string","pattern":"^(new|contacted|closed)$","title":"Status"}},"type":"object","required":["status"],"title":"LeadPatch"},"LensIn":{"properties":{"text":{"type":"string","maxLength":1200,"minLength":3,"title":"Text"}},"type":"object","required":["text"],"title":"LensIn"},"LoginIn":{"properties":{"email":{"type":"string","title":"Email"},"password":{"type":"string","title":"Password"}},"type":"object","required":["email","password"],"title":"LoginIn"},"MT5ConnectIn":{"properties":{"login":{"type":"string","maxLength":32,"minLength":1,"title":"Login"},"server":{"type":"string","maxLength":80,"minLength":1,"title":"Server"}},"type":"object","required":["login","server"],"title":"MT5ConnectIn"},"MarkPaidIn":{"properties":{"payout_ref":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Payout Ref"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["reason"],"title":"MarkPaidIn"},"MarkupIn":{"properties":{"markup":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Markup","description":"null resets to the global rate"},"reason":{"type":"string","title":"Reason"},"acknowledge_below_cost":{"type":"boolean","title":"Acknowledge Below Cost","default":false}},"type":"object","required":["reason"],"title":"MarkupIn"},"ModuleIn":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["enabled"],"title":"ModuleIn"},"OnboardingIn":{"properties":{"experience":{"type":"string","title":"Experience"},"capital":{"items":{"type":"string"},"type":"array","maxItems":3,"title":"Capital"},"markets":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Markets"},"goals":{"items":{"type":"string"},"type":"array","maxItems":4,"title":"Goals"},"skipped":{"type":"boolean","title":"Skipped","default":false}},"type":"object","required":["experience"],"title":"OnboardingIn"},"OptimizeIn":{"properties":{"days":{"type":"integer","maximum":2000.0,"minimum":200.0,"title":"Days","default":730}},"type":"object","title":"OptimizeIn"},"OrderIn":{"properties":{"side":{"type":"string","pattern":"^(long|short)$","title":"Side"},"sl":{"type":"number","exclusiveMinimum":0.0,"title":"Sl"},"tp":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Tp"},"risk_pct":{"type":"number","maximum":5.0,"minimum":0.1,"title":"Risk Pct","default":1.0},"conviction":{"anyOf":[{"type":"integer","maximum":5.0,"minimum":1.0},{"type":"null"}],"title":"Conviction"},"conviction_note":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Conviction Note"}},"type":"object","required":["side","sl"],"title":"OrderIn"},"PackIn":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"credits":{"type":"number","exclusiveMinimum":0.0,"title":"Credits"},"price_usd":{"type":"number","exclusiveMinimum":0.0,"title":"Price Usd"},"active":{"type":"boolean","title":"Active","default":true},"sort":{"type":"integer","title":"Sort","default":0},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["name","credits","price_usd","reason"],"title":"PackIn"},"PaperIn":{"properties":{"days":{"type":"integer","maximum":365.0,"minimum":14.0,"title":"Days","default":90}},"type":"object","title":"PaperIn"},"PasswordIn":{"properties":{"current":{"type":"string","maxLength":200,"minLength":1,"title":"Current"},"new":{"type":"string","maxLength":200,"minLength":10,"title":"New"}},"type":"object","required":["current","new"],"title":"PasswordIn"},"PayeeIn":{"properties":{"workspace_id":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Workspace Id"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["workspace_id","reason"],"title":"PayeeIn"},"PayoutIn":{"properties":{"payout_method":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Payout Method"},"payout_details":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Payout Details"}},"type":"object","title":"PayoutIn"},"PayoutRunIn":{"properties":{"hold_days":{"type":"integer","maximum":180.0,"minimum":0.0,"title":"Hold Days","default":30},"min_payout_usd":{"type":"number","maximum":100000.0,"minimum":0.0,"title":"Min Payout Usd","default":50.0},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","title":"PayoutRunIn"},"PlanIn":{"properties":{"commission_type":{"type":"string","pattern":"^(one_time|recurring)$","title":"Commission Type"},"commission_pct":{"type":"number","maximum":100.0,"exclusiveMinimum":0.0,"title":"Commission Pct"},"spend_pct":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Spend Pct"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["commission_type","commission_pct","reason"],"title":"PlanIn"},"PortalIn":{"properties":{"return_url":{"type":"string","title":"Return Url"}},"type":"object","required":["return_url"],"title":"PortalIn"},"PositionIn":{"properties":{"ticket":{"type":"string","maxLength":40,"title":"Ticket","default":""},"symbol":{"type":"string","maxLength":40,"title":"Symbol","default":""},"side":{"type":"string","maxLength":6,"title":"Side","default":""},"qty":{"type":"number","title":"Qty","default":0.0},"open_t":{"type":"integer","title":"Open T","default":0},"open_px":{"type":"number","title":"Open Px","default":0.0},"sl":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Sl"},"tp":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Tp"},"profit":{"type":"number","title":"Profit","default":0.0},"swap":{"type":"number","title":"Swap","default":0.0}},"type":"object","title":"PositionIn","description":"One open position, as MetaTrader sees it."},"PrefsIn":{"properties":{"channel_inapp":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Channel Inapp"},"channel_email":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Channel Email"},"digest_weekly":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Digest Weekly"},"improvements":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Improvements"},"decay_alerts":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Decay Alerts"}},"type":"object","title":"PrefsIn"},"PricingIn":{"properties":{"value":{"type":"number","title":"Value"},"reason":{"type":"string","title":"Reason"},"acknowledge_below_cost":{"type":"boolean","title":"Acknowledge Below Cost","default":false}},"type":"object","required":["value","reason"],"title":"PricingIn"},"ProfileIn":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name"}},"type":"object","required":["name"],"title":"ProfileIn"},"ProofIn":{"properties":{"value":{"type":"string","title":"Value"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["value","reason"],"title":"ProofIn"},"ProviderTokenIn":{"properties":{"id_token":{"type":"string","maxLength":8192,"minLength":16,"title":"Id Token"},"ref":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Ref"}},"type":"object","required":["id_token"],"title":"ProviderTokenIn"},"ProvisionIn":{"properties":{"email":{"type":"string","title":"Email"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"provider":{"type":"string","title":"Provider","default":"google"},"provider_sub":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Sub"},"ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ref"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"}},"type":"object","required":["email"],"title":"ProvisionIn"},"PublishBody":{"properties":{"strategy_id":{"type":"string","maxLength":64,"minLength":1,"title":"Strategy Id"},"price_credits":{"anyOf":[{"type":"integer","maximum":100000.0,"minimum":0.0},{"type":"null"}],"title":"Price Credits"}},"type":"object","required":["strategy_id"],"title":"PublishBody"},"ReadSpecIn":{"properties":{"text":{"type":"string","maxLength":20000,"title":"Text","default":""},"markets":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":2000},{"type":"null"}],"title":"Markets"},"market":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Market"}},"type":"object","title":"ReadSpecIn"},"RegimeIn":{"properties":{"regime":{"type":"string","pattern":"^(coach|exam)$","title":"Regime"}},"type":"object","required":["regime"],"title":"RegimeIn"},"RejectIn":{"properties":{"reason":{"type":"string","title":"Reason"}},"type":"object","required":["reason"],"title":"RejectIn"},"RenameIn":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"}},"type":"object","required":["name"],"title":"RenameIn"},"ResetIn":{"properties":{"token":{"type":"string","maxLength":200,"minLength":16,"title":"Token"},"password":{"type":"string","maxLength":200,"minLength":1,"title":"Password"}},"type":"object","required":["token","password"],"title":"ResetIn"},"ResetOut":{"properties":{"ok":{"type":"boolean","title":"Ok"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["ok"],"title":"ResetOut"},"RewriteIn":{"properties":{"feedback":{"type":"string","maxLength":2000,"title":"Feedback","default":""}},"type":"object","title":"RewriteIn"},"RoleIn":{"properties":{"role":{"type":"string","title":"Role"}},"type":"object","required":["role"],"title":"RoleIn"},"SaveIn":{"properties":{"name":{"type":"string","maxLength":140,"minLength":1,"title":"Name"},"spec":{"additionalProperties":true,"type":"object","title":"Spec"},"source_text":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Source Text"},"market":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Market"},"tf":{"anyOf":[{"type":"string","maxLength":8},{"type":"null"}],"title":"Tf"},"verdict":{"anyOf":[{"type":"string","maxLength":24},{"type":"null"}],"title":"Verdict"},"last_backtest":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Last Backtest"},"status":{"type":"string","maxLength":24,"title":"Status","default":"backtested"},"project_id":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Project Id"},"code":{"anyOf":[{"type":"string","maxLength":60000},{"type":"null"}],"title":"Code"},"class_name":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Class Name"}},"type":"object","required":["name"],"title":"SaveIn"},"ScreenIn":{"properties":{"spec":{"additionalProperties":true,"type":"object","title":"Spec"},"tf":{"type":"string","title":"Tf","default":"H1"},"days":{"type":"integer","maximum":400.0,"minimum":30.0,"title":"Days","default":90},"worth_days":{"type":"integer","maximum":3700.0,"minimum":90.0,"title":"Worth Days","default":730},"lookback_bars":{"type":"integer","maximum":20.0,"minimum":1.0,"title":"Lookback Bars","default":3},"markets":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Markets"}},"type":"object","required":["spec"],"title":"ScreenIn"},"SdkBacktestIn":{"properties":{"code":{"type":"string","maxLength":64000,"minLength":1,"title":"Code"},"class_name":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Class Name"},"market":{"type":"string","maxLength":40,"minLength":1,"title":"Market"},"tf":{"type":"string","title":"Tf","default":"H1"},"days":{"type":"integer","maximum":100000.0,"minimum":30.0,"title":"Days","default":365}},"type":"object","required":["code","market"],"title":"SdkBacktestIn"},"SettlePayoutIn":{"properties":{"reference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["reason"],"title":"SettlePayoutIn"},"ShareIn":{"properties":{"user_id":{"type":"string","maxLength":32,"minLength":1,"title":"User Id"},"permission":{"type":"string","title":"Permission","default":"viewer"}},"type":"object","required":["user_id"],"title":"ShareIn"},"SimulateIn":{"properties":{"strategy_id":{"type":"string","title":"Strategy Id"},"source":{"type":"string","pattern":"^(backtest|paper)$","title":"Source","default":"backtest"},"market":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market"},"tf":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tf"},"days":{"type":"integer","maximum":3650.0,"minimum":30.0,"title":"Days","default":365},"risk_pct":{"type":"number","maximum":10.0,"exclusiveMinimum":0.0,"title":"Risk Pct","default":1.0}},"type":"object","required":["strategy_id"],"title":"SimulateIn","description":"[SPEC 2026-07-31] Owner: \"choose between testing our real trading performance, or testing any\nstrategy we created, or backtest and see if it will survive the prop account\"."},"StaffRoleIn":{"properties":{"role":{"type":"string","pattern":"^(none|support|admin|superadmin)$","title":"Role"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["role","reason"],"title":"StaffRoleIn"},"StartIn":{"properties":{"strategy_id":{"type":"string","maxLength":40,"minLength":1,"title":"Strategy Id"},"mode":{"type":"string","pattern":"^(paper|live)$","title":"Mode","default":"paper"},"market":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Market"},"tf":{"anyOf":[{"type":"string","maxLength":8},{"type":"null"}],"title":"Tf"},"risk_pct":{"type":"number","maximum":100.0,"exclusiveMinimum":0.0,"title":"Risk Pct","default":1.0},"note":{"type":"string","maxLength":200,"title":"Note","default":""}},"type":"object","required":["strategy_id"],"title":"StartIn"},"StepIn":{"properties":{"n":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"N","default":1}},"type":"object","title":"StepIn"},"StopIn":{"properties":{"reason":{"type":"string","maxLength":200,"title":"Reason","default":""}},"type":"object","title":"StopIn"},"StrategyBody":{"properties":{"strategy_id":{"type":"string","maxLength":64,"minLength":1,"title":"Strategy Id"}},"type":"object","required":["strategy_id"],"title":"StrategyBody"},"SyncIn":{"properties":{"account_label":{"type":"string","maxLength":80,"title":"Account Label","default":"default"},"login":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Login"},"server":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Server"},"company":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Company"},"currency":{"type":"string","maxLength":8,"title":"Currency","default":"USD"},"balance":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Balance"},"equity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Equity"},"margin_free":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Margin Free"},"reported_t":{"type":"integer","title":"Reported T","default":0},"ea_version":{"anyOf":[{"type":"string","maxLength":24},{"type":"null"}],"title":"Ea Version"},"closed":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Closed"},"positions":{"anyOf":[{"items":{"$ref":"#/components/schemas/PositionIn"},"type":"array"},{"type":"null"}],"title":"Positions"}},"type":"object","title":"SyncIn"},"TierIn":{"properties":{"tier":{"type":"string","pattern":"^(free|pro|trader|enterprise)$","title":"Tier"},"reason":{"type":"string","title":"Reason"},"contract_mrr_usd":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Contract Mrr Usd"},"grant_credits":{"type":"boolean","title":"Grant Credits","default":true}},"type":"object","required":["tier","reason"],"title":"TierIn"},"ValidateIn":{"properties":{"spec":{"additionalProperties":true,"type":"object","title":"Spec"},"market":{"type":"string","maxLength":40,"minLength":1,"title":"Market"},"tf":{"type":"string","title":"Tf","default":"H1"},"days":{"type":"integer","maximum":100000.0,"minimum":90.0,"title":"Days","default":730}},"type":"object","required":["spec","market"],"title":"ValidateIn"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VisibilityIn":{"properties":{"visibility":{"type":"string","title":"Visibility"}},"type":"object","required":["visibility"],"title":"VisibilityIn"},"VoidCommissionIn":{"properties":{"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","title":"VoidCommissionIn"},"WorkspaceIn":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name"}},"type":"object","required":["name"],"title":"WorkspaceIn"},"api__external_signals__BacktestIn":{"properties":{"market":{"type":"string","maxLength":32,"minLength":1,"title":"Market"},"tf":{"type":"string","pattern":"^(M5|M15|M30|H1|H4|D)$","title":"Tf","default":"H1"},"days":{"type":"integer","maximum":3650.0,"minimum":1.0,"title":"Days","default":365},"signals":{"items":{"$ref":"#/components/schemas/api__external_signals__SignalIn"},"type":"array","maxItems":20000,"minItems":1,"title":"Signals"},"sl_atr":{"type":"number","maximum":20.0,"exclusiveMinimum":0.0,"title":"Sl Atr","default":1.5},"tp":{"type":"string","maxLength":32,"title":"Tp","default":"atr:2"}},"type":"object","required":["market","signals"],"title":"BacktestIn"},"api__external_signals__SignalIn":{"properties":{"t":{"type":"integer","title":"T","description":"bar time, epoch SECONDS (the bar the entry is taken on)"},"side":{"type":"string","pattern":"^(long|short)$","title":"Side"}},"type":"object","required":["t","side"],"title":"SignalIn"},"api__projects__CreateIn":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"parent_id":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Parent Id"},"brain_learn":{"type":"boolean","title":"Brain Learn","default":true}},"type":"object","required":["name"],"title":"CreateIn"},"api__projects__PatchIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Name"},"set_parent":{"type":"boolean","title":"Set Parent","default":false},"parent_id":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Parent Id"},"brain_learn":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Brain Learn"}},"type":"object","title":"PatchIn"},"api__replay__CreateIn":{"properties":{"market":{"type":"string","maxLength":24,"minLength":1,"title":"Market"},"tf":{"type":"string","title":"Tf"},"start_t":{"type":"integer","exclusiveMinimum":0.0,"title":"Start T"}},"type":"object","required":["market","tf","start_t"],"title":"CreateIn"},"api__replay__SignalIn":{"properties":{"strategy_id":{"type":"string","maxLength":64,"minLength":1,"title":"Strategy Id"}},"type":"object","required":["strategy_id"],"title":"SignalIn"},"api__signals__SignalIn":{"properties":{"bars":{"items":{"$ref":"#/components/schemas/BarIn"},"type":"array","maxItems":5000,"minItems":300,"title":"Bars"},"market":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Market"},"tf":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tf"}},"type":"object","required":["bars"],"title":"SignalIn","description":"Recent CLOSED candles, oldest first, on the strategy's own timeframe. >=300 so indicators and\nstructure are warm at the last bar; capped so a poll can't smuggle in a full backtest."},"api__strategies__PatchIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":140},{"type":"null"}],"title":"Name"},"spec":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Spec"},"status":{"anyOf":[{"type":"string","maxLength":24},{"type":"null"}],"title":"Status"},"verdict":{"anyOf":[{"type":"string","maxLength":24},{"type":"null"}],"title":"Verdict"},"last_backtest":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Last Backtest"},"set_project":{"type":"boolean","title":"Set Project","default":false},"project_id":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Project Id"},"brain_learn":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Brain Learn"}},"type":"object","title":"PatchIn"},"api__wizard__BacktestIn":{"properties":{"spec":{"additionalProperties":true,"type":"object","title":"Spec"},"market":{"type":"string","maxLength":40,"minLength":1,"title":"Market"},"tf":{"type":"string","title":"Tf","default":"M15"},"days":{"type":"integer","maximum":100000.0,"minimum":30.0,"title":"Days","default":365},"modes":{"items":{"type":"string"},"type":"array","maxItems":4,"title":"Modes"},"name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Name"},"job_id":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Job Id"}},"type":"object","required":["spec","market"],"title":"BacktestIn"}}}}