For the complete documentation index, see llms.txt. This page is also available as Markdown.

42 - Action Center

Overview

The Action Center is a centralized order approval system for semi-automated trading. When enabled, orders are queued for manual approval before execution, essential for managed accounts and regulatory compliance (RA - Relationship Advisor mode).

Architecture Diagram

Action Center architecture: order services call should_route_to_pending, semi-auto orders are queued to pending_orders and surfaced via Socket.IO in the React Action Center, approved orders are executed by execute_approved_order

Order Mode Configuration

Setting Order Mode

Mode Toggle API

Both user_id and mode are required. mode must be exactly auto or semi_auto; anything else returns HTTP 400.

Semi-Auto Workflow

Semi-auto flow: immediate-execution check, order mode check, queue_order stores and emits, then approve, reject or ignore in the Action Center

Database Schema

pending_orders Table

Indexes

Executor-Supported Queued Types

API Type
Description
Service called on approval

placeorder

Standard order

place_order_service.place_order

smartorder

Position-aware order

place_smart_order_service.place_smart_order

basketorder

Multiple orders

basket_order_service.place_basket_order

splitorder

Split large orders

split_order_service.split_order

optionsorder

Options contracts

place_options_order_service.place_options_order

optionsmultiorder

Multi-leg options order

options_multiorder_service.place_options_multiorder

placegttorder

GTT order placement

place_gtt_order_service.place_gtt_order

Approval dispatch in services/pending_order_execution_service.py handles these seven API types. Any other api_type is answered with Unknown order type: <api_type> and HTTP 400, and the row's broker status is set to rejected.

placegttorder is handled specially on success: the executor stores the broker's trigger_id as broker_order_id and sets broker_status to open. If the GTT placement succeeds without a trigger ID, the row is marked rejected and the call returns HTTP 502.

calculate_action_center_stats() reports a counter per API type as well: total_placeorder, total_smartorder, total_basketorder, total_splitorder, total_optionsorder, total_optionsmultiorder and total_placegttorder.

Restricted Operations

These operations are never queued. Read-only operations execute immediately; destructive operations apply their own service policy and are blocked in semi-auto mode unless analyzer behavior explicitly permits them. The set is IMMEDIATE_EXECUTION_OPERATIONS in services/order_router_service.py, and should_route_to_pending() compares against it case-insensitively.

Operation
Reason

closeposition

Blocked by close-position service in semi-auto live mode

closeallpositions

Blocked by close-position service in semi-auto live mode

cancelorder

Blocked by cancel-order service in semi-auto live mode

cancelallorder

Blocked by cancel-all service in semi-auto live mode

modifyorder

Blocked by modify-order service in semi-auto live mode

modifygttorder / cancelgttorder

Blocked because a delayed change may target a stale trigger

gttorderbook

Data retrieval

orderstatus

Status query

orderbook

Data retrieval

tradebook

Data retrieval

positions / openposition

Data retrieval

holdings

Data retrieval

funds

Data retrieval

API Endpoints

All Action Center routes are defined on orders_bp (blueprints/orders.py, url_prefix="/") and require a valid session. Every route except /action-center/count also carries @limiter.limit(API_RATE_LIMIT).

Endpoint
Method
Description

/action-center

GET

Server-rendered page (the React SPA serves the same path)

/action-center/api/data

GET

Orders and statistics as JSON

/action-center/approve/<order_id>

POST

Approve and execute one order

/action-center/reject/<order_id>

POST

Reject one order

/action-center/delete/<order_id>

DELETE

Delete one non-pending order

/action-center/approve-all

POST

Approve and execute every pending order

/action-center/count

GET

Pending count for the nav badge

Get Orders

status accepts pending, approved, rejected or all, and defaults to pending. Statistics are always calculated over all of the user's orders, not just the filtered subset.

Response:

raw_order_data is the stored payload with apikey and api_key stripped out.

Approve Order

Response:

If the order is approved but broker execution fails, the response is {"status": "warning", "message": "Order approved but execution failed", "error": "..."} returned with the service's own status code.

Reject Order

Approve All

Response:

status is success when every approved order executed, warning when some executed, and error when none did. With nothing pending, the response is {"status": "info", "message": "No pending orders to approve"}.

Delete Order

Note: Only approved or rejected orders can be deleted.

Get Pending Count

Response:

Real-Time Updates

SocketIO Events

Event
Trigger
Data

pending_order_created

New order queued by order_router_service.queue_order()

pending_order_id, user_id, api_type, message

pending_order_updated

Approve, reject, delete or approve-all

action (approved, rejected, deleted or batch_approved), order_id, user_id. The batch variant sends count instead of order_id

pending_order_created is emitted through socketio.start_background_task() and is best-effort: if the emit fails, the queued row still stands and the caller still receives a success response.

Frontend Handling

React Component Features

Tabbed Interface

Statistics Dashboard

Order Table Columns

Column
Content

Strategy

Strategy name

Symbol

Trading symbol

Exchange

NSE/NFO/MCX badge

Action

BUY (green) / SELL (red)

Quantity

Order quantity

Price

Price or "MARKET"

Order Type

placeorder/smartorder/etc

Product

CNC/MIS/NRML badge

Created

Relative time ("5 min ago")

Actions

Approve/Reject/Delete buttons

Expandable Details

Click chevron to view raw order data:

Service Implementation

Order Router

Any exception inside should_route_to_pending() is caught and returns False, so an unexpected failure falls back to immediate execution rather than silently queueing.

Queue Order

Execute Approved Order

Passing auth_token and broker into the service is what stops the approved order from being routed back into the pending queue a second time. If any of api_key, auth_token or broker is missing, the row is marked rejected and the call returns HTTP 403.

Batch responses (basket and split orders) are flattened by _flatten_execution_results() and the resulting broker order IDs are joined into the 255 character broker_order_id column, truncated to <first_id> (+N more) when they do not fit.

Security & Compliance

Audit Trail

All actions are logged with:

  • Timestamp (IST)

  • Username

  • Action taken

  • Reason (for rejections)

API Key Security

  • API keys never stored in pending_orders

  • Only user_id reference maintained

  • Keys retrieved at execution time

Analyzer Mode Restriction

When in semi_auto mode, the API-key path of the analyzer toggle (services/analyzer_service.py) is blocked with HTTP 403 to ensure SEBI Research Analyst compliance: mode switching stays a client-only decision made through the UI. Internal calls that already carry auth_token and broker are not affected.

Key Files Reference

File
Purpose

database/action_center_db.py

PendingOrder model

services/action_center_service.py

Order parsing, stats

services/order_router_service.py

Route decisions

services/pending_order_execution_service.py

Execute approved

blueprints/orders.py

Action center routes

blueprints/apikey.py

Mode toggle

frontend/src/pages/ActionCenter.tsx

React UI

Last updated

Was this helpful?