Overview
Everything your team needs to integrate with the Apt. platform — REST endpoints, WebSocket feeds, and Flutter WebView embedding.
Two-phase integration
| Phase | Workstream | Owner |
| Phase 1 | Backend API | Your API / OMS team |
| Phase 2 | Frontend SDK | Your mobile / web team |
ℹIf any endpoint is unavailable, reach out — we're happy to discuss alternatives or a phased rollout.
Integration steps
| # | Task | Notes |
| 1 | Authentication setup | Token expiry, refresh flow, API key generation |
| 2 | IP whitelisting | Share Apt. server IPs for your firewall |
| 3 | Provision test accounts | 3 accounts with Equity & F&O on NSE + BSE |
| 4 | Backend endpoints | REST + WebSocket per this spec |
| 5 | Instrument master CSV | Daily downloadable, token → symbol mapping |
| 6 | Flutter WebView embed | Per Frontend SDK sections |
| 7 | UAT | End-to-end testing before go-live |
What's in this doc
| Section | Endpoints |
| Order Management | Place · Modify · Cancel |
| Positions & Order Book | Order history · Live positions |
| Account & Funds | Margin · Available cash |
| WebSocket Feeds | Order updates · LTP |
| Market Data | Instrument CSV · OHLC · LTP fallback |
| Flutter WebView | Loading state · Error handling |
| JS Channel Bridge | Web → Flutter messaging |
| File Downloads | Android DownloadManager |
Authentication
Prerequisite for all endpoints. No changes from the v1 specification. Please confirm the items below before integration testing.
⚠Confirm token expiry duration and the full refresh flow before we begin.
Items to confirm
| Item | Detail needed |
| API key generation | Portal, email, or programmatic? |
| Token expiry | How long does a session token remain valid? |
| Refresh flow | Refresh token, or full re-authentication? |
| IP whitelisting | Must requests come from whitelisted IPs? |
| Auth rate limits | Are login/refresh calls rate-limited separately? |
Test Accounts
Three accounts required before integration testing begins. All must have Equity & F&O access on NSE and BSE with limited testing funds.
| # | Account | Segments | Exchanges |
| 1 | Test Account 1 | Equity & F&O | NSE and BSE |
| 2 | Test Account 2 | Equity & F&O | NSE and BSE |
| L | Live / Staging Account | Equity & F&O | NSE and BSE |
✓Share credentials via a secure channel. Provision before UAT begins.
Order Management
Three endpoints for placing, modifying, and cancelling orders. All responses must include the broker order ID and a timestamp.
POST 1. Place Order
Submit a new order to the exchange.
Request fields
| Field | Type | Values | |
symbol | string | Trading symbol | Required |
exchange | string | NSE · BSE | Required |
quantity | integer | Number of units | Required |
price | decimal | Limit price; 0 for MKT | Required |
product_type | enum | MIS · CNC · NRML | Required |
order_type | enum | MKT · LMT · SL · SL-M | Required |
validity | enum | DAY · IOC | Required |
Response fields
| Field | Type | Description |
broker_order_id | string | Unique order ID from your OMS |
timestamp | ISO 8601 | Order acceptance time |
PUT 2. Modify Order
Edit an open or pending order.
ℹResponse must confirm the updated order state — not just a success code.
| Field | Type | Notes |
broker_order_id | string | Target order |
quantity | integer | New quantity |
price | decimal | New limit price |
trigger_price | decimal | SL / SL-M only |
order_type | enum | MKT · LMT · SL · SL-M |
DELETE 3. Cancel Order
Cancel an open or pending order by broker order ID.
⚠If the order is already executed or cancelled, return an appropriate error — not a silent success.
| Field | Type |
broker_order_id | string |
Positions & Order Book
Read endpoints for order history and live position data including P&L.
GET 4. Order History / Order Book
All orders for the session across every status.
Required statuses
PENDING→
OPEN→
EXECUTED/
CANCELLED/
REJECTED/
FAILED
Required response fields
| Field | Type | Notes |
broker_order_id | string | Your OMS reference |
exchange_order_id | string | Exchange-assigned ID |
placed_at | ISO 8601 | Order placement time |
updated_at | ISO 8601 | Last status update time |
rejection_reason | string | Populated for REJECTED / FAILED |
GET 5. Positions
Intraday (MIS) and overnight (NRML) positions across all states.
| Field | Type | Notes |
average_price | decimal | Average entry price |
ltp | decimal | Last traded price |
pnl_realised | decimal | Realised P&L |
pnl_unrealised | decimal | Unrealised P&L |
quantity | integer | Net open quantity |
product_type | enum | MIS · NRML |
status | enum | open · closed · partially_closed |
Account & Funds
Margin and funds data for pre-order checks. Called before placing orders to validate sufficient margin.
GET 6. Funds / Limits
Must return values separately for Equity and F&O segments.
| Field | Type | Notes |
available_cash | decimal | Free cash available |
used_margin | decimal | Margin blocked by open positions |
collateral | decimal | Pledged securities value |
available_margin | decimal | Net margin available for new orders |
WebSocket Feeds
Two real-time feeds required for core platform functionality.
⚠Please share your WebSocket connection and reconnection behaviour documentation — heartbeat interval and max reconnect strategy.
WS 7. Order Update Feed
Real-time push for every order status transition.
Required transitions
PENDING→
OPEN→
EXECUTED/
CANCELLED/
REJECTED
ℹBoth broker_order_id and exchange_order_id must be present in every event.
Required event fields
| Field | Type | Notes |
broker_order_id | string | Must be in every event |
exchange_order_id | string | Must be in every event |
status | enum | New status after transition |
timestamp | ISO 8601 | Event time |
WS 8. LTP Feed
Token-based live price subscription for real-time P&L and watchlist prices.
| Parameter | Requirement |
| Subscription model | Token-based (instrument token) |
| Minimum tokens | 3,000 per connection |
| Maximum tokens | 10,000 per connection |
| Tick frequency | Please confirm |
| Partial subscription updates | Please confirm |
Market Data
Instrument master, OHLC candles, and REST LTP fallback.
9. Instrument Master (CSV)
Daily downloadable CSV: token → symbol mapping for all subscriptions and order routing.
✓Regenerate and publish at a fixed URL by market open each day.
| Column | Type | Notes |
token | integer | Used in WebSocket subscriptions |
trading_symbol | string | Exchange-standard symbol |
exchange | string | NSE · BSE · NFO · BFO |
instrument_type | string | EQ · FUT · CE · PE |
lot_size | integer | F&O instruments |
tick_size | decimal | Minimum price movement |
expiry | date | F&O only; blank for EQ |
GET 10. OHLC / Historical Candles
| Parameter | Requirement |
| Timeframes | 1m · 15m · 1h · 1d |
| Candles per call | Minimum 5,000 |
| Rate limit target | >20 req/sec — document if lower |
Required fields per candle
| Field | Type | Notes |
open | decimal | |
high | decimal | |
low | decimal | |
close | decimal | |
volume | integer | |
oi | integer | F&O only — Open Interest |
GET 11. LTP REST Fallback
Fetch last traded price when the WebSocket LTP feed is unavailable or not yet connected.
ℹCan be skipped if the LTP WebSocket reliably auto-reconnects with no data gap.
Flutter WebView
Embed the Apt. web app inside your Flutter app with proper loading and error states.
Loading state
Show a spinner while content loads — prevents users seeing a blank screen.
| Event | Action |
onPageStarted | Set isLoading = true |
onPageFinished | Set isLoading = false |
controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(NavigationDelegate(
onPageStarted: (url) => setState(() => isLoading = true),
onPageFinished: (url) => setState(() => isLoading = false),
))
..loadRequest(Uri.parse('https://webtest.atoms.trade'));
// In build():
Stack(children: [
WebViewWidget(controller: controller),
if (isLoading)
Container(
color: Colors.white,
child: const Center(child: CircularProgressIndicator()),
),
])
Error handling
Show an error screen instead of a blank page on load failure.
Error events
| Event | Description |
onHttpError | HTTP errors (404, 500, etc.) |
onWebResourceError | Network failures, timeouts, DNS issues |
onPageStarted | Reset error state on retry |
Error screen must include
| Element | Detail |
| Error icon | Icons.error_outline |
| Message | "Unable to load page" |
| Subtext | "Please check your internet connection" |
| Retry button | Calls controller.reload() |
JS Channel Bridge
Communication between the Apt. web app and your Flutter host via a named JavaScript channel.
Channel spec
| Property | Value |
| Channel name | FlutterChannel |
| Supported message | navigateToHome |
| Purpose | Navigate back to the Flutter home screen |
⚠Available only inside the Flutter WebView. Message must exactly match navigateToHome — anything else is silently ignored.
Flutter — register channel
controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..addJavaScriptChannel(
'FlutterChannel',
onMessageReceived: (JavaScriptMessage message) {
if (message.message == 'navigateToHome') {
widget.onNavigateToHome();
}
},
);
Web app — send a message
window.FlutterChannel.postMessage('navigateToHome');
File Downloads
Download files to the Android Downloads folder using Flutter's MethodChannel and Android's DownloadManager.
ℹReplace YOUR_PACKAGE_NAME with your Android app ID — e.g. com.example.myapp.
Flutter setup
pubspec.yaml
dependencies:
url_launcher: ^6.2.0
Download function
final _downloadChannel = MethodChannel('YOUR_PACKAGE_NAME/download');
Future<void> triggerDownload(String url, {String? fileName}) async {
final name = fileName ?? url.split('/').last.split('?').first;
final safeName = name.isNotEmpty ? name : 'download';
if (Platform.isAndroid) {
try {
final id = await _downloadChannel.invokeMethod<dynamic>(
'downloadFile', {'url': url, 'fileName': safeName},
);
if (id != null) return;
} catch (e) { debugPrint('Download failed: $e'); }
}
final uri = Uri.tryParse(url);
if (uri != null && await canLaunchUrl(uri)) {
await launchUrl(uri, mode: LaunchMode.externalApplication);
}
}
Trigger from WebView
Option A — JS messaging (preferred)
window.FlutterChannel?.postMessage(
JSON.stringify({ type: 'download', url: fileUrl })
);
Option B — Navigation interception (fallback)
onNavigationRequest: (NavigationRequest request) {
if (request.url.contains('.xlsx') ||
request.url.contains('amazonaws.com')) {
triggerDownload(request.url);
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
Integration Checklist
Track delivery against each item before go-live.
Backend API
- Place Order — returns
broker_order_id + timestamp
- Modify Order — confirms updated order state
- Cancel Order — returns error for already-executed orders
- Order Book — all 6 statuses, both order IDs, timestamps, rejection reason
- Positions — MIS + NRML, all states, avg price, LTP, realised + unrealised P&L
- Funds — available cash, used margin, collateral, available margin per segment
- Order Update WebSocket — all transitions, both order IDs per event
- LTP WebSocket — 3k–10k token range, tick frequency confirmed
- Instrument Master CSV — all 7 columns, daily refresh confirmed
- OHLC Candles — 4 timeframes, 5k candles/call, OI for F&O
- Authentication — token expiry and refresh flow documented
Frontend SDK
- WebView loads Apt. URL with loading indicator
- Error screen on HTTP/network failures with retry
FlutterChannel registered and navigateToHome handled
- JS messaging download trigger implemented
- Navigation interception fallback for file URLs
- Android DownloadManager with correct package name
Ops & Access
- 3 test accounts provisioned (Equity + F&O, NSE + BSE)
- IP whitelisting requirements confirmed
- WebSocket reconnection behaviour documented
- Rate limits documented for all endpoints
Rate Limits & Open Items
Items needing your confirmation before integration testing begins.
| Item | Our requirement | Action needed |
| OHLC rate limit | >20 req/sec | Confirm; document if lower |
| LTP WebSocket tick frequency | As fast as possible | Confirm actual frequency |
| LTP partial subscription updates | Must be supported | Confirm |
| WebSocket reconnect behaviour | Auto-reconnect, no data gap | Share reconnection docs |
| Token expiry duration | — | Confirm duration |
| IP whitelisting | Apt. server IPs | Confirm requirements |
ℹIf any endpoint is unavailable, reach out — we are happy to discuss workarounds or a phased rollout.