API Overview

TraderTape exposes a REST API for everything the UI does. You can use it directly to script strategy management, programmatic backtesting, custom dashboards, and integrations.

This document is a high-level overview, not a complete reference. For the auto-generated OpenAPI spec, see the link at the end.

Base URL

https://tradertape.com/api/...

All endpoints live under /api/. There are no API versioning prefixes โ€” the backend is single-version, breaking changes are announced via the changelog.

Authentication

Every endpoint that touches user data requires authentication via a session cookie:

Cookie: kite_session=<session_token>

To get a session token, complete the magic link or password login flow:

# Step 1: request a magic link
curl -X POST https://tradertape.com/api/auth/magic-link \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com"}'

# Step 2: click the link in your email (or use the OTP)
# Step 3: the verify endpoint sets the kite_session cookie automatically

For programmatic use, prefer the agent API key path:

# Generate an agent API key in Settings โ†’ Trading Agent
# Then use it as a Bearer token:
curl https://tradertape.com/api/agent/pending-signals \
  -H "Authorization: Bearer zt_abc123..."

The agent API key is scoped to your account and can be revoked / regenerated at any time.

Common patterns

List + filter

Most "list" endpoints accept query parameters for filtering and pagination:

GET /api/strategies?is_active=true&is_template=false&limit=20&offset=0

Create

POST /api/strategies
Content-Type: application/json

{
  "name": "My Strategy",
  "base_model": "v3_dip_buyer",
  "entry_rules": {...},
  ...
}

Update

PUT /api/strategies/{id}
Content-Type: application/json

{
  "name": "My Strategy v2",
  ...
}

Updates are full replacements (PUT, not PATCH). The full strategy body is required.

Delete

DELETE /api/strategies/{id}

Major resources

Strategies

GET    /api/strategies                    List your strategies
POST   /api/strategies                    Create
GET    /api/strategies/{id}               Get one
PUT    /api/strategies/{id}               Update
DELETE /api/strategies/{id}               Delete
POST   /api/strategies/{id}/fork          Fork (creates a new strategy under your account)
POST   /api/strategies/{id}/share         Toggle is_public

Backtest

POST   /api/backtest/run                  Run a backtest synchronously
GET    /api/backtest/runs                 List your backtest history
GET    /api/backtest/runs/{id}            Get one with full per-trade detail
DELETE /api/backtest/runs/{id}            Delete a run

A backtest run typically takes 2-10 seconds to complete. The endpoint blocks until done.

Model Portfolios

GET    /api/model/portfolios              List active portfolios
POST   /api/model/portfolios/deploy       Deploy a new portfolio
GET    /api/model/dashboard?portfolio_id=N   Full dashboard payload
POST   /api/model/portfolios/{id}/pause   Pause
POST   /api/model/portfolios/{id}/resume  Resume
POST   /api/model/portfolios/{id}/retire  Retire (must have no open positions)
POST   /api/model/portfolios/{id}/reset   Reset (paper portfolios only)
POST   /api/model/scan                    Trigger a manual scan

Signals

GET    /api/model/signals?portfolio_id=N&status=pending_approval   List signals
POST   /api/model/signals/{id}/approve    Move to in_cart
POST   /api/model/signals/{id}/reject     Mark rejected
POST   /api/model/signals/{id}/expire     Force expire
POST   /api/model/cart/place              Place all in_cart signals as GTTs

Positions

GET    /api/model/positions?portfolio_id=N&status=open  List
POST   /api/model/positions/{id}/close                  Manual close

Tradebook upload

POST   /api/uploads/tradebook    multipart/form-data, field "files[]" โ€” XLSX files
POST   /api/uploads/ledger       multipart/form-data, field "file"  โ€” XLSX file
POST   /api/uploads/cas          multipart/form-data, field "file"  โ€” PDF

Risk rules

GET    /api/risk/rules                     List your active rules
POST   /api/risk/rules                     Create a new rule
PUT    /api/risk/rules/{id}                Update
DELETE /api/risk/rules/{id}                Delete
GET    /api/risk/state                     Current state (today's loss, exposure, etc.)

Holdings, positions, orders (live broker data)

GET    /api/portfolio/holdings    Live broker holdings
GET    /api/portfolio/positions   Live broker positions (intraday + delivery)
GET    /api/portfolio/orders      Live broker orders
GET    /api/portfolio/margins     Available cash and margin

These endpoints proxy directly to the broker API after using your active session. Cached for ~30 seconds to avoid rate limits.

Family groups

GET    /api/family/groups                  List groups you're a member of
POST   /api/family/groups                  Create a new group
POST   /api/family/groups/{id}/invite      Invite by email
POST   /api/family/groups/{id}/accept      Accept an invitation
GET    /api/family/consolidated            Family-wide totals

Auth

POST   /api/auth/magic-link                Request a magic link
POST   /api/auth/verify-link               Verify magic link OR OTP
POST   /api/auth/password-login            Password login
POST   /api/auth/logout                    Clear session
GET    /api/auth/me                        Current user info, broker connection status
GET    /api/auth/status                    Broker session status (separate from user session)
GET    /api/auth/kite-credentials          Stored Kite credentials
POST   /api/auth/kite-credentials          Save Kite credentials

Agent API

For local agent integration (Authorization: Bearer zt_... header):

GET    /api/agent/pending-signals          Signals to execute
POST   /api/agent/signal-result            Report a fill / failure
POST   /api/agent/sync-holdings            Push holdings snapshot to cloud
POST   /api/agent/sync-positions           Push positions snapshot
GET    /api/agent/pending-token            Poll for a pending Kite request_token
POST   /api/agent/access-token             Push a freshly exchanged Kite access_token

WebSocket

WS /api/ws/ticks

Send subscribe / unsubscribe messages:

{"action": "subscribe", "symbols": ["NSE:RELIANCE", "NSE:INFY"], "mode": "quote"}
{"action": "unsubscribe", "symbols": ["NSE:RELIANCE"]}

Receive tick messages:

{"type": "ticks", "data": {"NSE:RELIANCE": {"ltp": 2580.5, "high": 2592, "low": 2545, ...}}}
{"type": "status", "connected": true}
{"type": "subscribed", "symbols": ["NSE:INFY"]}

Error responses

All errors follow the FastAPI default shape:

{
  "detail": "Human-readable error message"
}

Common HTTP status codes:

  • 200 / 201 โ€” success
  • 400 โ€” bad request (invalid params, business logic violation)
  • 401 โ€” not authenticated (no valid session cookie)
  • 403 โ€” authenticated but not authorized (e.g. trying to modify another user's data)
  • 404 โ€” resource not found
  • 409 โ€” conflict (e.g. trying to delete a strategy that has active portfolios)
  • 422 โ€” request body validation failed (Pydantic schema mismatch)
  • 500 โ€” internal server error

For unexpected errors, the response includes a sanitized error message โ€” internal stack traces are never exposed.

Rate limits

There are no formal API rate limits at the moment. If you're scripting heavy traffic, throttle yourself to a few requests per second.

Pagination

List endpoints accept limit and offset query params:

GET /api/model/signals?limit=50&offset=100

Default limit varies by endpoint โ€” typically 50 or 100. Maximum is 500.

Schema reference

The full OpenAPI spec is auto-generated and available at:

https://tradertape.com/api/docs

(Subject to access controls โ€” may require authentication.)

Examples

Run a backtest

import requests

session = requests.Session()
session.cookies.set("kite_session", "your-session-token")

response = session.post("https://tradertape.com/api/backtest/run", json={
    "strategy_id": 42,
    "universe": "nifty_100",
    "start_date": "2020-01-01",
    "end_date": "2026-01-01",
    "starting_capital": 10000000,
    "position_size_pct": 10,
    "max_positions": 20,
    "max_per_sector": 2,
    "slippage_bps": 5,
})

result = response.json()
print(f"CAGR: {result['summary']['cagr']:.1f}%")
print(f"Win rate: {result['summary']['win_rate']:.1f}%")
print(f"Total trades: {result['summary']['total_trades']}")

List pending signals

response = session.get("https://tradertape.com/api/model/signals", params={
    "status": "pending_approval",
    "portfolio_id": 7,
})

for signal in response.json():
    print(f"{signal['symbol']}: conviction={signal['conviction']}")

Subscribe to live ticks

import websocket
import json

ws = websocket.WebSocket()
ws.connect("wss://tradertape.com/api/ws/ticks", cookie="kite_session=...")

ws.send(json.dumps({
    "action": "subscribe",
    "symbols": ["NSE:RELIANCE", "NSE:INFY"],
    "mode": "quote"
}))

while True:
    msg = json.loads(ws.recv())
    if msg["type"] == "ticks":
        for symbol, tick in msg["data"].items():
            print(f"{symbol}: {tick['ltp']}")

What the API doesn't expose

A few internal endpoints aren't part of the public API:

  • Admin endpoints (/api/auth/admin/...) โ€” only accessible with is_admin = true
  • Internal scan triggers โ€” the scanner runs from a background task, not via a public endpoint (the manual /api/model/scan is the user-facing equivalent)
  • Database introspection โ€” no SQL endpoint, no schema dump

Stability

The API is not versioned and may change between releases. Breaking changes are announced in the changelog. The frontend is updated in lockstep with the backend, so the deployed UI and the API are always compatible.

For most casual scripting, the API has been stable enough that day-to-day usage rarely breaks. If you're building a long-lived integration, watch the changelog for breaking-change notices.

Next