# go-market API go-market is an intraday trading backend that integrates with the Fyers brokerage API. All endpoints except /health, /auth/token, and /public/redirect require a Bearer JWT in the Authorization header. ## Authentication ### POST /auth/token Obtain a JWT for protected endpoints. Request body: { "username": string, "password": string } Response: { "token": string } ### GET /auth/login Get the Fyers OAuth login URL. Requires JWT. Response: { "url": string } Open the returned URL in a browser to complete OAuth. On completion Fyers redirects to /public/redirect. ### GET /auth/status Check whether the current user has a valid Fyers token. Response: { "valid": bool, "reason": string (only when valid=false) } ### POST /auth/logout Revoke the current user's Fyers token and stop the market data feed. Response: { "message": string } ### GET /public/redirect Fyers OAuth callback — not for direct use. ## Subscriptions ### POST /subscriptions Subscribe to real-time market data and historical backfill for one or more symbols. Request body: { "symbols": [string] } Response: 204 No Content ### GET /subscriptions List all subscribed symbols with the status of their latest backfill job. Response: [{ "symbol": string, "latestJob": { "id": string, "trigger": string, "status": string, "error": string } | null }] ### DELETE /subscriptions?symbol= Unsubscribe from a symbol and clear its in-memory data. Response: 204 No Content ### POST /subscriptions/backfill?symbol= Manually trigger a historical data backfill for an already-subscribed symbol. Response: 202 Accepted — { "jobId": string } ### GET /subscriptions/warmup/:jobId Poll the status of a backfill job. Response: { "id": string, "symbol": string, "trigger": string, "status": string, "error": string } ## Market Data ### GET /ltp/:symbol Get the current last-traded price for a symbol. Response: { "symbol": string, "ltp": number, "tickAt": string (RFC3339) } ### GET /candles/:symbol Get candles for a subscribed symbol. Supports two modes: **Latest mode** (no from/to): returns the most recent N candles from memory. Query params: timeframe (1m|5m|15m|1h, default 1m), limit (default 50) **Range mode** (from+to required together): returns a paginated time-range query from the database. Query params: from (unix seconds), to (unix seconds), timeframe (1m|5m|15m|1h, default 1m), limit (default 1000, max 10000), offset (default 0) Response: { "symbol": string, "timeframe": string, "candles": [{ "symbol": string, "timestamp": number (unix seconds), "open": number, "high": number, "low": number, "close": number, "volume": number }], "total": number (range mode only) } ## Strategies (Sessions) ### POST /strategies/register Register a new strategy session. Request body: { "sessionId": string, "strategyName": string, "mode": "paper"|"live", "autoSquareOff": string (RFC3339, optional) } Response: 204 No Content ### GET /strategies List all strategy sessions for the current user. Response: [{ "id": string, "username": string, "strategyName": string, "mode": string, "autoSquareOff": string | null, "squaredOff": bool, "createdAt": string }] ### GET /strategies/:sessionId Get a single strategy session by ID. Response: same session object shape ## Trades ### POST /trades Place a trade against a session. Paper orders fill immediately at LTP; live orders are sent to Fyers as market orders. Request body: { "sessionId": string, "symbol": string, "side": "BUY"|"SELL", "qty": number } Response: 201 Created — { "id": string, "username": string, "sessionId": string, "strategyName": string, "symbol": string, "side": string, "requestedQty": number, "filledQty": number, "avgFillPrice": number, "status": string, "fyersOrderId": string (live only), "createdAt": string, "updatedAt": string } ### GET /trades?from=&to=&sessionId=&symbol= List trades for the current user within a time range. from and to are required (unix seconds). sessionId and symbol are optional filters. Response: [{ "id": string, "username": string, "sessionId": string, "strategyName": string, "symbol": string, "side": string, "requestedQty": number, "filledQty": number, "avgFillPrice": number, "status": string, "fyersOrderId": string (live only), "createdAt": string, "updatedAt": string }] ## Positions ### GET /positions?sessionId= Derive open positions from trades. sessionId is optional; omitting it returns positions across all sessions. Response: [{ "sessionId": string, "strategyName": string, "symbol": string, "netQty": number, "avgPrice": number, "currentLtp": number, "unrealizedPnl": number }] ### POST /positions/squareoff?sessionId= Square off all open positions in a session at current LTP and mark it as squared-off. Response: the open positions that were closed (same shape as GET /positions) ## Health ### GET /health Service health check (no auth required). Response: { "status": "ok", "db": "ok"|"error" }