Documentation

dotQuant is a trading platform with agentic behaviours — live market data, charts and AI analyst coverage for every symbol you track, and automated broker execution from TradingView alerts, your own code, or an AI assistant.

Getting Started

Introduction

dotQuant is a trading platform with agentic behaviours — AI analyst coverage, live market data, and automated broker execution.

dotQuant is a trading platform built around agentic behaviours — AI analysts review every symbol you follow, and the whole platform can be operated by AI assistants through open protocols.

Explore instantly — no account needed: Search any stock, ETF or index, build a watchlist, stream live price charts, and follow the latest news, straight from the browser. Every symbol you track is automatically reviewed by a panel of AI analyst agents that score its fundamentals and publish a bullish, neutral, or bearish stance with a full scoring breakdown — see Meet the AI Analysts below.

Register to make it yours: Creating an account keeps your watchlist across devices and unlocks the account-bound features — broker connections, TradingView signal routing, and API keys for programmatic and AI-assistant access.

Automate your trading: Connect your broker (Interactive Brokers via the dotQuant Desktop App) and route trade signals to it automatically — from TradingView alerts, from your own code via the BaaS API, or from an MCP-connected AI assistant.

Agentic by design: The agents are not just a research feature. dotQuant exposes its full capability surface through the BSP manifest and the MCP server, so external AI assistants — Claude, Cursor, and other MCP-capable tools — can discover what your account can do and operate it under your authentication, the same way the dashboard does.

⚖️

Risk Disclosure: Trading involves significant risk. Automated trading systems can experience transient technical issues, such as network latency or connectivity disruptions, which may lead to unexpected execution results. Automated execution does not guarantee profit, and you may lose some or all of your invested capital.

Meet the AI Analysts

Six AI analyst personas — each with a distinct investment philosophy — run analysis on every symbol you track.

When you add a symbol to your watchlist, dotQuant automatically runs an AI analysis for it. Each agent independently reviews the company's fundamentals through the lens of its own investment style and publishes a bullish, neutral, or bearish signal with a category-by-category scoring breakdown. The combined picture appears in the Fundamentals Matrix on the symbol page, and each agent's full reasoning is one click away.

The agents below are fictional personas. Their output is informational only and is not financial advice or an endorsement by any real person.

Margaret Holloway Deep Value “Buy a dollar for fifty cents.”

Find financially sturdy companies trading at a clear discount to intrinsic value, protected by a hard margin of safety.

  • Insist on a margin of safety — buy below intrinsic value (Graham Number, net-net).
  • Demand financial strength: low leverage and ample liquidity.
  • Prefer stable earnings across multiple years.
  • Treat a consistent dividend record as extra safety.
  • Avoid speculation and high-growth assumptions; trust proven metrics.
Howard Sterling Quality Compounder “Wonderful businesses at fair prices, held for the long run.”

Own durable, high-return businesses with honest management and buy them with a meaningful margin of safety.

  • Stay within a circle of competence — only invest in businesses you understand.
  • Buy well below intrinsic value for a margin of safety.
  • Prefer companies with a lasting economic moat.
  • Back conservative, shareholder-oriented management.
  • Demand financial strength: low debt and strong returns on equity.
  • Think in decades — own businesses, not tickers.
Arthur Pennington Moat & Management “A wonderful business with honest managers, bought at a fair price.”

Concentrate in predictable, high-return businesses with deep moats and trustworthy management, and never overpay.

  • Focus on the quality and predictability of the business.
  • Use mental models from multiple disciplines to analyze investments.
  • Look for strong, durable competitive advantages (moats).
  • Emphasize long-term thinking and patience.
  • Value management integrity and competence.
  • Prioritize businesses with high returns on invested capital.
  • Pay a fair price for wonderful businesses, always demanding a margin of safety.
  • Avoid complexity and businesses you don't understand — invert, always invert.
Marcus Crane Activist Quality “Great businesses, concentrated bets, hands-on when it counts.”

Hold a concentrated portfolio of high-quality businesses and push for change where management can unlock value.

  • Seek high-quality businesses with durable competitive advantages (moats).
  • Prioritize consistent free cash flow and growth potential.
  • Insist on financial discipline: reasonable leverage and efficient capital allocation.
  • Target intrinsic value with a margin of safety.
  • Invest with high conviction in a concentrated portfolio for the long term.
  • Take an activist approach when operational or management changes can unlock value.
Nadia Vance Disruptive Growth “Bet on the technologies reshaping the next decade.”

Back companies riding disruptive innovation toward exponential growth in very large markets.

  • Seek companies leveraging disruptive innovation.
  • Emphasize exponential growth potential and a large total addressable market.
  • Focus on technology, healthcare, and other future-facing sectors.
  • Think in multi-year horizons for breakthroughs to compound.
  • Accept higher volatility in pursuit of outsized returns.
  • Back management with vision and the willingness to invest in R&D.
Sofia Reyes Macro Momentum “Asymmetric bets — big when right, small when wrong.”

Ride growth and momentum with asymmetric risk-reward, sizing up on conviction and cutting losses fast.

  • Seek asymmetric risk-reward opportunities — large upside, limited downside.
  • Emphasize growth, momentum, and market sentiment.
  • Preserve capital by avoiding major drawdowns.
  • Pay up for true growth leaders when the thesis warrants it.
  • Be aggressive when conviction is high.
  • Cut losses quickly when the thesis changes.

The Signal Bridge

From TradingView alerts to broker execution — the original core of dotQuant.

dotQuant has evolved from a simple TradingView-to-broker signal bridge into a full market data platform. It combines live and historical price data, automated trade signal execution, and an open API — giving you the building blocks for systematic trading strategies without depending on a single data source.

Market data: dotQuant streams live price bars and historical data through a platform-managed integration. Price feeds are configured per symbol — you subscribe to a feed and dotQuant handles sourcing the data.

Trade execution: TradingView alerts and BaaS API commands are still fully supported. Configured signals route to your connected broker (IBKR via the Desktop App, or Trading 212 via cloud) exactly as before.

Open by design: Every capability is accessible via the BSP/BaaS API and the MCP server, so AI agents and custom scripts can interact with your account the same way the UI does.

TradingViewAlerts & StrategiesWebhookdotQuantTechnical BridgeExecutionBrokersInteractive Brokers

Quick Start Guide

Five steps to connect TradingView to your broker.

1. Connect Broker: Visit the 'Brokers' tab in your dashboard and connect your IBKR Gateway via the dotQuant Desktop App.
2. Create a Signal: Create an 'Indicator' or 'Strategy' entry under your broker in dotQuant. dotQuant generates a TradingView alert message pre-configured with your alert ID and broker details.
3. Webhook URL: Copy the fixed webhook URL shown on the signal settings page: https://api.dotquant.io/webhook/v1/submit-signal.
4. TradingView Alert: Create an alert on any TradingView chart. In the 'Notifications' tab, paste the Webhook URL.
5. JSON Message: In the 'Message' field, paste the auto-generated JSON message from your signal settings page. Your next alert will now trigger a live order.

Core Concepts

How dotQuant works.

Price Feeds: A price feed subscribes to live and historical bar data for a specific symbol. Feeds are configured in the Feeds section of your dashboard — pick a symbol, interval, and connector type. dotQuant polls for new bars every minute and broadcasts updates to all subscribers in real time.

Signals: JSON messages containing trade instructions — alert ID, action, symbol, quantity, and your broker account details. dotQuant auto-generates the correct format for each alert; you paste it into TradingView (or send it directly via the BaaS API).

Bridge: The dotQuant engine that authenticates an incoming signal via your Tenant ID, maps the instrument to your broker, and dispatches the order. TradingView webhooks, BaaS API calls, and MCP agent commands all flow through the same bridge.

Signal History: A persistent, immutable record of every incoming webhook and outgoing order result, visible on each broker page in the dashboard. Each entry shows the action, symbol, quantity, timestamp, and any broker error returned.

Broker Integration

Interactive Brokers (IBKR)

Hybrid local/cloud automation via the dotQuant Desktop App.

IBKR integration follows a unique multi-step path. dotQuant servers transmit orders via WebSockets to a dedicated dotQuant Desktop App installed on your computer. This app acts as a local bridge, forwarding the command to your running IBKR TWS or IB Gateway instance. This ensures your API keys and trading sessions stay within your local environment while still benefiting from cloud-based alerts.

dotQuant CloudOrder EngineWebSocketDesktop AppLocal dotQuantTWS APIIBKR TWSTrader Workstation

Live Market Data (IBKR)

Enabling real-time price feeds from TWS in the dotQuant dashboard.

The dotQuant Desktop App subscribes to live market data via the TWS API for any symbol that has an active indicator or strategy. This powers the live price chart visible on your broker dashboard.

Why market data may be unavailable

IBKR requires separate market data subscriptions for each exchange. If you see a 'Live market data unavailable' notice on your broker page, it means TWS returned one of the following errors:

- Error 354 — The symbol is not subscribed. Go to IBKR Client Portal → Settings → Market Data Subscriptions and enable the relevant exchange data package (e.g. NASDAQ Top of Book for US equities).
- Error 10089 — The subscription exists but an additional add-on is required. In TWS, open the Market Data Connections dialog (under the Help or Connectivity menu) and subscribe to the required feed directly.
- Error 10090 — Insufficient permissions for the requested data tier. Review your active subscriptions in IBKR Client Portal → Settings → Market Data Subscriptions.

Paper trading accounts: Market data subscriptions on paper accounts are separate from live accounts. You may need to subscribe independently for each environment.

Duplicate notifications: The Desktop App suppresses repeated errors for the same symbol and error code within a 60-second window, so the notice will not re-appear immediately after dismissal unless a new error is received.

Market Data

Platform-managed live and historical price feeds.

dotQuant streams live and historical price data through a built-in market data integration. You do not need a third-party data account or API key.

Subscribing to a feed

Go to the Feeds section of your dashboard and add a new feed. Enter a symbol and exchange (e.g. MSFT on NASDAQ, or BTC/USD on COINBASE PRO). dotQuant will start streaming live 1-minute bars to your dashboard in real time.

Intervals

Live polling uses a 1-minute interval. Historical data loaded when you change the chart period uses daily bars.

Symbol format

- Equities: TICKER + exchange (e.g. MSFT on NASDAQ)
- Crypto: BASE/QUOTE + exchange (e.g. BTC/USD on COINBASE PRO)
- Non-US equities: enter the local exchange (e.g. ENI on BVME)

TradingView as a signal source only

TradingView is supported for trade signals (webhook alerts → broker execution) but is not a market data source in dotQuant. Price charts are powered exclusively by dotQuant's built-in data feeds.

Trading 212 (T212)

Cloud-to-cloud automation using direct HTTP APIs.

⚠️ Experimental. Trading 212 integration is provided as-is and is not generally available — Interactive Brokers is dotQuant's fully supported broker.

Trading 212 integration is a direct cloud-to-cloud connection. Once you provide your T212 API key, dotQuant servers communicate directly with the Trading 212 HTTP endpoints. No local software is required to maintain this connection.

dotQuant CloudSignal ProcessorDirect HTTP APITrading 212Live / Demo API

Encryption & Security

Zero-knowledge approach to your API credentials.

Your broker credentials are encrypted using AES-256 with keys managed in a secure Hardware Security Module (HSM). dotQuant employees cannot view your API keys, and they are only decrypted in memory during the brief moment required to send an order to your broker.

Write-only credentials: Once saved, your API keys and secrets are never returned to the browser or displayed in clear text. The settings page will always show empty credential fields — this is by design. To update your credentials, simply enter new values and save. Your existing credentials remain active until replaced.

T212 Live mode (experimental): In Live mode, your API Key and API Secret are combined and encoded before transmission, then encrypted server-side. Both fields must be re-entered together when updating, as they cannot be retrieved individually.

Signal Management

Indicator vs Strategy

Choosing the right configuration type.

Indicators: Use these for simple price alerts or study signals (e.g., 'RSI Overbought'). These usually trigger a single action.
Strategies: Use these when using TradingView's strategy() functions. dotQuant can interpret complex strategy alerts that include entry and exit commands in a single alert stream.

Allow Partial Exits

Handling strategies with staged or partial exits.

When a TradingView strategy uses multiple strategy.exit() calls per entry, each exit fires a separate webhook with its own partial quantity. The Allow Partial Exits toggle (strategy alerts only) controls how dotQuant handles these sell signals.

Off (default): Every exit signal closes the full position on the broker in one go, regardless of the quantity in the webhook. This is the safe default for strategies that use a single strategy.close() or one strategy.exit().

On: Each exit signal sends the exact quantity from TradingView to the broker as a market sell order, allowing your strategy to scale out of a position gradually.

Example — tiered take-profit strategy:

strategy.exit("TP1", from_entry="Long", qty_percent=50, limit=tp1_price)
strategy.exit("TP2", from_entry="Long", qty_percent=50, limit=tp2_price)

With Allow Partial Exits on, the first webhook sells 50% and the second sells the remaining 50%. With it off, the first webhook would close the entire position.

Important notes:
- Buy signals are not affected — this setting only changes behaviour for sell/exit orders.
- Market orders only — limit orders are not affected by this toggle.
- Your Pine Script exits should sum to 100% of the entry. dotQuant does not track position state — it trusts the quantities TradingView provides.

Position Sizing

Configure how trade quantity is determined.

dotQuant supports three ways to specify position size:

Fixed Value: Enter a specific number of shares or contracts. The quantity you set will be used for every trade.

From TradingView Plot: Let your Pine Script calculate the quantity dynamically. Your script must include a plot() statement with a named output (e.g., plot(myQty, "Quantity")). dotQuant will read this value at alert time using {{plot("Quantity")}}.

From Strategy Order (Strategies only): Use the built-in {{strategy.order.contracts}} placeholder to pass through whatever quantity your TradingView strategy calculates.

📊 Fixed Value
You specify: 10 shares
→ Webhook sends: "quantity": "10"
📈 From TradingView Plot
Pine Script: plot(myQty, "Quantity")
→ Webhook sends: "quantity": "{{plot(\"Quantity\")}}"
🎯 From Strategy Order Strategies only
Uses built-in TradingView placeholder
→ Webhook sends: "quantity": "{{strategy.order.contracts}}"

Dynamic Position Sizing

Advanced techniques using TradingView plots.

Dynamic position sizing from TradingView is powerful for:

Risk-based sizing: Risk 1% of your account per trade — quantity varies based on stop distance.

Volatility-based sizing: Use ATR to size positions smaller in volatile markets.

Signal strength sizing: Stronger signals can trigger larger positions.

Kelly criterion: Mathematically optimal sizing based on your win rate and payoff ratio.

To use dynamic sizing, add a plot() in your Pine Script:

myQuantity = math.floor(accountRisk / stopDistance)
plot(myQuantity, "PositionSize")

Then select 'From TradingView Plot' in dotQuant and enter 'PositionSize' as the plot name.

Payload Structure

The JSON format sent from TradingView to dotQuant.

The TradingView alert message is auto-generated by dotQuant — you copy it from your signal settings page and paste it into the TradingView alert Message field. There is no manual formatting required.

dotQuant generates a JSON object with these fields:

- alert_id — your alert's unique ID (hard-coded; ties each signal to the right alert)
- symbol — the instrument symbol (hard-coded, or {{ticker}} if left dynamic)
- date{{timenow}} (TradingView fills this at alert time)
- data — the action: buy, sell, or {{strategy.order.action}} for strategies
- quantity — fixed number, {{plot("PlotName")}}, or {{strategy.order.contracts}}
- price{{close}}
- order_typeMKT or LMT
- inst_typeSTK, Forex, Crypto, or Options
- accounts — array containing your Tenant ID, Broker ID, and Broker Name

Do not write or edit this JSON manually. Always copy the auto-generated message from your signal settings page to ensure all IDs are correct.

The Journal

Reviewing your execution history.

The Order Journal provides a 'raw view' of the communication between TradingView, dotQuant, and your broker. If an order fails, the Journal will display the exact error message returned by the broker API, making it easy to troubleshoot issues like 'Insufficient Margin' or 'Invalid Symbol'.

API Reference

Webhook Endpoint

Technical details for sending signals programmatically.

Endpoint: POST https://api.dotquant.io/webhook/v1/submit-signal

Content-Type: application/json

This is the TradingView-facing endpoint. The auto-generated message from your signal settings page is designed for this endpoint — the accounts[].account_id (your Tenant ID) embedded in the payload is how the bridge identifies you.

Example payload (as auto-generated by dotQuant for an indicator alert):

{
  "alert_id": "<your-alert-id>",
  "symbol": "AAPL",
  "date": "{{timenow}}",
  "data": "buy",
  "quantity": "10",
  "price": "{{close}}",
  "order_type": "MKT",
  "inst_type": "STK",
  "accounts": [
    {
      "account_id": "<your-tenant-id>",
      "broker_id": "<your-broker-id>",
      "broker_name": "IBKR"
    }
  ]
}


For strategy alerts, data is {{strategy.order.action}} and quantity uses {{strategy.order.contracts}} or a plot reference. Copy the auto-generated message from your signal settings page rather than constructing this payload by hand.

Journal API

Reviewing your execution history.

Signal and execution history is available through the broker endpoints in the BaaS API:

Signals for a broker:
GET https://baas.dotquant.io/tenants/{tenantId}/api/brokers/{brokerName}/{brokerId}/signals

Returns the signals received for the specified broker account.

Authentication: Required (X-Api-Key header)

The dotQuant dashboard uses these same endpoints to display the signal list on each broker page. For bulk export or custom reporting, call this endpoint directly with your API Key.

System Health

Checking whether the dotQuant API is reachable.

A liveness endpoint is available at:

GET https://api.dotquant.io/healthz

Returns 200 OK with the text Healthy when the API process is running. This is a basic process-level liveness check — it does not report on database connectivity, message queue status, or broker connection state. Use it to confirm the API is reachable, not to infer the health of downstream services.

BSP Integration

What is BSP?

Open Agent Protocol for AI agent integration.

BSP (Behavioral State Protocol) enables AI agents to interact with dotQuant programmatically. Agents discover available capabilities via a standard manifest at /.well-known/bsp and interact through structured endpoints.

dotQuant models each configured broker account as an BSP agent. Agents accept TradingView signals (SignalReceived) and produce trade commands (ConfigureBroker, ConfigureIndicatorAlert, etc.).

Discovery flow:
1. Agent fetches /.well-known/bsp
2. Reads the manifest — services, capabilities, agents
3. Starts interacting without any hard-coded integration

Spec: openagentprotocol.io

BSP Discovery Manifest

The discovery endpoint for AI agents.

Root manifest (informational): GET /.well-known/bsp

Declares the platform and provides the URI template for tenant manifests. Has no capabilities of its own:

{
  "BSP": {
    "version": "0.4.16",
    "tenants": {
      "manifest": "https://dotquant.io/api/bsp/tenants/{tenantId}/.well-known/bsp"
    },
    "services": {
      "io.dotquant.trading": {
        "description": "Market data and trade signal execution platform",
        "rest": { "endpoint": "https://dotquant.io/" }
      }
    },
    "capabilities": [],
    "authentication": { "type": "bearer", "scheme": "Bearer" }
  }
}


Tenant manifest (canonical): GET /api/bsp/tenants/{tenantId}/.well-known/bsp

Fully self-contained manifest for your account. Contains capability definitions with resolved endpoint paths. This is the manifest AI agents should use.

List Agents

Retrieve configured broker agents (io.bsp.agents.registry).

Endpoint: GET /api/bsp/tenants/{tenantId}/agents

Authentication: Required (Bearer API Key)

Returns configured broker accounts as BSP agent descriptors. Each agent includes the event types it accepts and the command types it can produce:

{
  "agents": [
    {
      "id": "broker-001",
      "name": "Interactive Brokers",
      "type": "ibkr",
      "accepts": ["SignalReceived"],
      "produces": ["ConfigureBroker", "ArchiveBroker", "ConfigureIndicatorAlert", "..." ],
      "status": "running"
    }
  ]
}


status values:
- running — broker is connected
- paused — broker is configured but not connected

Query Events

Retrieve TradingView signal events (io.bsp.agents.events).

Endpoint: GET /api/bsp/tenants/{tenantId}/events

Authentication: Required (Bearer API Key)

Query Parameters:
- hours (optional, default: 24): Time window in hours
- agentId (optional): Filter by broker agent ID
- commandId (optional): Filter by alert ID

Returns TradingView signals as BSP events — immutable observed facts received by broker agents:

{
  "events": [
    {
      "id": "sig-001",
      "type": "SignalReceived",
      "agentId": "broker-001",
      "agentName": "Interactive Brokers",
      "commandId": "alert-001",
      "symbol": "AAPL",
      "action": "buy",
      "quantity": 10,
      "timestamp": "2026-02-12T10:30:00Z",
      "error": null
    }
  ],
  "count": 1
}

List Commands

Observe commands produced by agents (io.bsp.agents.commands).

Endpoint: GET /api/bsp/tenants/{tenantId}/commands

Authentication: Required (Bearer API Key)

Returns the command catalogue — all command types this tenant can accept, each with a dataschema URI pointing to the full JSON Schema:

{
  "commands": [
    {
      "schema": "configure-indicator-alert",
      "version": "1.0",
      "dataschema": "https://dotquant.io/api/bsp/tenants/{tenantId}/commands/configure-indicator-alert/1.0",
      "description": "Creates or updates an indicator-based alert."
    },
    {
      "schema": "submit-signal",
      "version": "1.0",
      "dataschema": "https://dotquant.io/api/bsp/tenants/{tenantId}/commands/submit-signal/1.0",
      "description": "Submit a TradingView trading signal for broker execution."
    }
  ]
}


type values: ConfigureIndicatorAlert or ConfigureStrategyAlert

Authentication

How agents authenticate with BSP endpoints.

All BSP endpoints (except the manifest) require authentication using your dotQuant API Key.

Header Format:

Authorization: Bearer <your-api-key>


Where to find your credentials — go to your Account page in the dashboard:
- Tenant ID: shown at the top right of the Account card, labelled Tenant ID
- API Key: shown in the API Keys section. Click Generate New API Key if you haven't created one yet.

Error Response (401 Unauthorized):
{
  "error": "API key required"
}


Scope: All endpoints are scoped to the authenticated tenant — you can only access your own agents, events, and commands. The authentication field in the manifest (type: "bearer") follows the BSP v0.4.16 standard.

Agent Use Cases

Examples of how AI agents can use the BSP Integration.

Portfolio Status Check:
Agent: "Show me signals from the last 24 hours"
→ Calls GET /api/bsp/tenants/{tenantId}/events?hours=24

Broker Health Monitoring:
Agent: "Are my brokers connected?"
→ Calls GET /api/bsp/tenants/{tenantId}/agents and checks status === 'running'

Alert Inventory:
Agent: "What commands can I send?"
→ Calls GET /api/bsp/tenants/{tenantId}/commands to get the full catalogue

Error Investigation:
Agent: "Show me failed signals"
→ Calls GET /api/bsp/tenants/{tenantId}/events and filters results where error is not null

dotQuant Broker Agent Model:
Each broker account accepts SignalReceived events (from TradingView webhooks) and produces commands like ConfigureIndicatorAlert, PauseStrategyAlert, ArchiveBroker, etc.

Agentic AI

Agentic AI Overview

AI agents that can trade on your behalf.

dotQuant is fully compliant with the BSP (Behavioral State Protocol), enabling AI assistants — such as Claude, Cursor, and other MCP-capable tools — to discover your trading capabilities and execute commands on your behalf, authenticated under your account.

Two transports are available:

REST transport: AI agents call dotquant.io directly using your API Key. The SvelteKit server acts as a secure proxy — it validates authentication, then forwards requests to BaaS server-side. Your API Key is the only credential needed by the agent.

MCP transport: Use dotquant-mcp (stdio) to connect any MCP-compatible AI tool to your dotQuant account. Install it locally and configure it with your API Key and Tenant ID.

All agentic interactions are scoped to your tenant — an agent can only access your own brokers, alerts, and signals.

Discovery

How agents find and connect to dotQuant.

dotQuant publishes two BSP manifests:

Service-level manifest (informational): GET https://dotquant.io/.well-known/bsp
Declares the platform exists and provides the URI template for tenant manifests. Has no capabilities of its own.

Tenant-scoped manifest (canonical): GET https://dotquant.io/api/bsp/tenants/{tenantId}/.well-known/bsp
Fully self-contained manifest for your account. Contains the resolved rest.endpoint, capability definitions, and available command catalogue URI. This is the manifest AI agents should use.

Discovery chain:

GET /.well-known/bsp
  → tenants.manifest URI template
    → GET /api/bsp/tenants/{tenantId}/.well-known/bsp
      → io.bsp.agents.commands capability
        → GET /api/bsp/tenants/{tenantId}/commands


Spec: openagentprotocol.io

Agent Authentication

How to authenticate as an AI agent.

All tenant-scoped BSP endpoints require authentication via your dotQuant API Key.Header format:

Authorization: Bearer <your-api-key>


Where to find your credentials — go to your Account page in the dashboard:
- Tenant ID: shown at the top right of the Account card, labelled Tenant ID. Use the copy button to copy it.
- API Key: shown in the API Keys section below. Click Generate New API Key if you haven't created one yet.

The key is tied to your Tenant ID — agents do not need to manage separate session tokens.

Security note: The SvelteKit proxy receives your Bearer token, extracts the key, and forwards it as X-Api-Key to the internal BaaS service. Your API Key is never stored in the browser or logs.

Command Catalogue

Listing available commands for your tenant.

Endpoint: GET /api/bsp/tenants/{tenantId}/commands

Authentication: Required (Bearer API Key)

Returns the list of command types your tenant supports, each with a link to its JSON Schema:

{
  "commands": [
    {
      "schema": "configure-indicator-alert",
      "version": "1.0",
      "description": "Configure an indicator-based alert",
      "dataschema": "https://dotquant.io/api/bsp/tenants/{tenantId}/commands/configure-indicator-alert/1.0"
    }
  ]
}


Each dataschema URI points to the full JSON Schema document for that command version.

Sending Commands

Executing a command via REST.

Endpoint: POST /api/bsp/tenants/{tenantId}/commands

Authentication: Required (Bearer API Key)

Content-Type: application/json

Commands are sent as CloudEvents wire format:

{
  "id": "unique-event-id",
  "type": "ConfigureIndicatorAlert",
  "source": "trading",
  "dataSchema": "configure-indicator-alert/1.0",
  "dataContentType": "application/json",
  "time": "2026-04-27T11:20:00Z",
  "data": {
    "CorrelationId": "<alert-stream-id>",
    "TenantId": "<your-tenant-id>",
    "BrokerId": "<your-broker-id>",
    "BrokerName": "IBKR",
    "Name": "AAPL Buy Signal",
    "Action": "Buy",
    "Symbol": "AAPL",
    "InstrumentType": "Stock",
    "OrderType": "Market",
    "QuantitySource": "FixedValue",
    "Quantity": 10
  }
}


Response (201 Created):
{ "id": "<alert-stream-id>" }


The command dataSchema must match a schema/version from the catalogue. The payload data must conform to the corresponding JSON Schema — fetch it first via GET /commands/{schema}/{version} to validate before sending.

Key field values:
- Action: Buy, Sell, or Close
- InstrumentType: Stock, Options, Forex, or Crypto
- OrderType: Market or Limit
- QuantitySource: FixedValue (requires Quantity) or FromTradingViewPlot (requires QuantityPlotName)

MCP Transport

Using dotquant-mcp with Claude, Cursor, and other tools.

The dotquant-mcp package exposes your dotQuant account as an MCP (Model Context Protocol) server, letting Claude Desktop, Cursor, and other MCP-compatible AI tools interact with your account natively.

Installation:

npm install -g dotquant-mcp


Configuration (add to your MCP client's config):
{
  "mcpServers": {
    "dotquant": {
      "command": "dotquant-mcp",
      "args": [],
      "env": {
        "DOTQUANT_API_KEY": "<your-api-key>",
        "DOTQUANT_TENANT_ID": "<your-tenant-id>"
      }
    }
  }
}


Once configured, your AI assistant can list your brokers, configure alerts, and send trade commands conversationally.

BaaS API

BaaS API Overview

Programmatic trading beyond TradingView.

The dotQuant BaaS API (baas.dotquant.io) is an HTTP API that lets you execute trades and manage your account programmatically — without TradingView webhooks.

Any application, script, or service can send orders directly to your connected broker using your API Key and Tenant ID. There are no restrictions on language or platform.

The API uses a command-based design: all write operations are CloudEvents sent to a single POST /tenants/{tenantId}/api/trading endpoint. Read operations use conventional GET endpoints. This is intentional — the system is built on event sourcing, so commands are dispatched to an internal message queue rather than modifying resources in-place.

Key capabilities:
- Submit buy/sell orders to your connected IBKR account
- Configure and manage indicator and strategy alerts
- Retrieve broker configuration and signal history
- Manage broker connections

Base URL: https://baas.dotquant.io

All endpoints are tenant-scoped: https://baas.dotquant.io/tenants/{tenantId}/...

API Key Authentication

How to authenticate with the BaaS API.

All BaaS API endpoints require your dotQuant API Key.Header format:

X-Api-Key: <your-api-key>


Where to find your credentials — go to your Account page in the dashboard:
- Tenant ID: shown at the top right of the Account card, labelled Tenant ID. Use the copy button to copy it. This goes into the {tenantId} path segment of every request.
- API Key: shown in the API Keys section below. Click Generate New API Key if you haven't created one yet.

Keep your API Key secret — it grants full access to your tenant.

Rate Limiting

Request limits enforced on all BaaS API endpoints.

Three independent limits are enforced on every request. All limits are per-instance and apply regardless of which endpoint is called.

1. Global limit — per IP address
120 requests per 60-second sliding window across all endpoints. Exceeding it returns 429 Too Many Requests with a Retry-After header (seconds to wait).

2. Write limit — per Tenant ID
Applies to POST and PUT on /tenants/{tenantId}/api/trading only (CloudEvent ingestion).
120 requests per 60-second sliding window. Same 429 + Retry-After response.

3. Auth failure limit — per IP address
If an IP sends 10 requests that result in 401 Unauthorized within a 60-second window, that IP is blocked for the remainder of the window.
Blocked requests receive 429 Too Many Requests with a Retry-After header.
The counter resets on a successful authenticated request — legitimate clients are never penalised.

Handling 429 responses
A 429 from any of the three limiters looks identical. Clients should treat them all the same way:
1. Read the Retry-After header value (integer, seconds)
2. Wait that duration before retrying
3. Do not retry immediately — the window will not have reset

# Example: check for 429 and honour Retry-After in bash
RESPONSE=$(curl -s -o /dev/null -w "%{http_code} %{header_json}" ...)
if [[ $RESPONSE == 429* ]]; then
  WAIT=$(echo $RESPONSE | jq -r '."retry-after"[0]')
  sleep $WAIT
fi


Note: The values above are the platform defaults. The operator-configured values in production may differ.

Submitting a Trade

Sending an order directly via the API.

Endpoint: POST https://baas.dotquant.io/tenants/{tenantId}/api/trading

Content-Type: application/json

All commands are sent as CloudEvents. To submit a trade signal:

{
  "id": "signal-msft-buy-001",
  "type": "SubmitSignal",
  "source": "trading",
  "dataSchema": "submit-signal/1.0",
  "dataContentType": "application/json",
  "time": "2026-04-27T11:20:00Z",
  "data": {
    "CorrelationId": "<your-alert-id>",
    "TenantId": "<your-tenant-id>",
    "Id": "<unique-signal-id>",
    "BrokerId": "<your-broker-id>",
    "BrokerName": "IBKR",
    "Symbol": "MSFT",
    "Date": "2026-04-27T11:20:00Z",
    "Data": "buy",
    "Quantity": 1,
    "Price": 424.60,
    "OrderType": "MKT",
    "InstrumentType": "STK",
    "AccountRiskPercentage": 0,
    "AccountQuantityMultiplier": 0
  }
}


Field notes:
- CorrelationId — the alert ID from your signal settings page (ties this signal to the right alert configuration)
- Id — a unique ID for this individual signal instance (sequential number or UUID)
- Data — the action: buy, sell, or close
- OrderTypeMKT or LMT
- InstrumentTypeSTK, Forex, Crypto, or Options
- AccountRiskPercentage / AccountQuantityMultiplier — set to 0 unless using account-level risk management

Response (202 Accepted):
{ "id": "<your-alert-id>" }


For a full list of supported command types and their schemas, call GET /tenants/{tenantId}/api/trading/schemas.

Command Schemas

Discovering supported command types.

List all schemas:
GET https://baas.dotquant.io/tenants/{tenantId}/api/trading/schemas

Returns:

[
  { "name": "submit-signal", "versions": ["1.0"] },
  { "name": "configure-indicator-alert", "versions": ["1.0"] },
  { "name": "configure-strategy-alert", "versions": ["1.0"] }
]


Fetch a specific schema:
GET https://baas.dotquant.io/tenants/{tenantId}/api/trading/schemas/{schema}/{version}

Returns the full JSON Schema document (application/schema+json) for that command version. Use this to validate your payloads before sending.

curl Examples

Ready-to-run curl commands for the BaaS API.

Replace $TENANT_ID, $API_KEY, $ALERT_ID, and $BROKER_ID with your values from the signal settings and Account pages.

List available command schemas:

curl https://baas.dotquant.io/tenants/$TENANT_ID/api/trading/schemas \
  -H "X-Api-Key: $API_KEY"


Fetch a specific schema (e.g. submit-signal v1.0):
curl https://baas.dotquant.io/tenants/$TENANT_ID/api/trading/schemas/submit-signal/1.0 \
  -H "X-Api-Key: $API_KEY"


Submit a buy order:
curl -X POST https://baas.dotquant.io/tenants/$TENANT_ID/api/trading \
  -H "X-Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "'$(uuidgen)'",
    "type": "SubmitSignal",
    "source": "trading",
    "dataSchema": "submit-signal/1.0",
    "dataContentType": "application/json",
    "time": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'",
    "data": {
      "CorrelationId": "'$ALERT_ID'",
      "TenantId": "'$TENANT_ID'",
      "Id": "'$(uuidgen)'",
      "BrokerId": "'$BROKER_ID'",
      "BrokerName": "IBKR",
      "Symbol": "AAPL",
      "Date": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'",
      "Data": "buy",
      "Quantity": 10,
      "Price": 200.00,
      "OrderType": "MKT",
      "InstrumentType": "STK",
      "AccountRiskPercentage": 0,
      "AccountQuantityMultiplier": 0
    }
  }'


Submit a sell order — same structure, change "Data": "sell":
curl -X POST https://baas.dotquant.io/tenants/$TENANT_ID/api/trading \
  -H "X-Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "'$(uuidgen)'",
    "type": "SubmitSignal",
    "source": "trading",
    "dataSchema": "submit-signal/1.0",
    "dataContentType": "application/json",
    "time": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'",
    "data": {
      "CorrelationId": "'$ALERT_ID'",
      "TenantId": "'$TENANT_ID'",
      "Id": "'$(uuidgen)'",
      "BrokerId": "'$BROKER_ID'",
      "BrokerName": "IBKR",
      "Symbol": "AAPL",
      "Date": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'",
      "Data": "sell",
      "Quantity": 10,
      "Price": 200.00,
      "OrderType": "MKT",
      "InstrumentType": "STK",
      "AccountRiskPercentage": 0,
      "AccountQuantityMultiplier": 0
    }
  }'


Windows (PowerShell):
$body = @{
  id = [guid]::NewGuid().ToString()
  type = "SubmitSignal"
  source = "trading"
  dataSchema = "submit-signal/1.0"
  dataContentType = "application/json"
  time = (Get-Date).ToUniversalTime().ToString("o")
  data = @{
    CorrelationId = $ALERT_ID
    TenantId = $TENANT_ID
    Id = [guid]::NewGuid().ToString()
    BrokerId = $BROKER_ID
    BrokerName = "IBKR"
    Symbol = "AAPL"
    Date = (Get-Date).ToUniversalTime().ToString("o")
    Data = "buy"
    Quantity = 10
    Price = 200.00
    OrderType = "MKT"
    InstrumentType = "STK"
    AccountRiskPercentage = 0
    AccountQuantityMultiplier = 0
  }
} | ConvertTo-Json -Depth 5

Invoke-RestMethod `
  -Uri "https://baas.dotquant.io/tenants/$TENANT_ID/api/trading" `
  -Method POST `
  -Headers @{ "X-Api-Key" = $API_KEY; "Content-Type" = "application/json" } `
  -Body $body

Use Cases

What you can build with the BaaS API.

Automated trading bot: A Python or Node.js script monitors market data and submits orders directly without needing TradingView.

Risk management layer: An external system monitors your positions and sends close orders if drawdown exceeds a threshold.

Multi-source signals: Combine signals from multiple sources (custom indicators, news feeds, ML models) and route them all to IBKR via the BaaS API.

Backtesting integration: Replay historical signals through the API in a paper-trading environment to validate execution logic.

Example — Python:

import requests, uuid
from datetime import datetime, timezone

requests.post(
    f"https://baas.dotquant.io/tenants/{tenant_id}/api/trading",
    headers={"X-Api-Key": api_key, "Content-Type": "application/json"},
    json={
        "id": str(uuid.uuid4()),
        "type": "SubmitSignal",
        "source": "trading",
        "dataSchema": "submit-signal/1.0",
        "dataContentType": "application/json",
        "time": datetime.now(timezone.utc).isoformat(),
        "data": {
            "CorrelationId": alert_id,
            "TenantId": tenant_id,
            "Id": str(uuid.uuid4()),
            "BrokerId": broker_id,
            "BrokerName": "IBKR",
            "Symbol": "AAPL",
            "Date": datetime.now(timezone.utc).isoformat(),
            "Data": "buy",
            "Quantity": 5,
            "Price": 200.00,
            "OrderType": "MKT",
            "InstrumentType": "STK",
            "AccountRiskPercentage": 0,
            "AccountQuantityMultiplier": 0
        }
    }
)

BETA