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 withis_admin = true - Internal scan triggers โ the scanner runs from a background task, not via a public endpoint (the manual
/api/model/scanis 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
- Architecture โ what each endpoint backs
- Strategies Guide โ high-level CRUD via the UI
- Backtesting Guide โ what
POST /api/backtest/rundoes