AI & Agents Integration
Learn how to connect Large Language Models, AI Agents, and Coding Assistants to the Index Alpha API.
Welcome to the AI & Agent Integration guide. Large Language Models (LLMs) and autonomous AI agents are the new developers. The Index Alpha API is designed from the ground up to be fully AI-friendly.
Whether you are building custom AI agents with frameworks like LangChain, running local desktop coding assistants like Cursor and GitHub Copilot, or configuring custom ChatGPT Actions / Claude Projects, we provide first-class tools and schemas to make integration seamless.
New: You can now connect Claude Desktop, Cursor, or any MCP-compatible client directly to our remote endpoint — no local server setup required. See the Remote MCP Connection guide for details.
1. Built-in LLM Documentation (llms.txt)
We support the emerging llms.txt standard, providing clean, context-optimized, and LLM-friendly documentation endpoints. If you are instructing an AI agent or search tool to learn about our API, simply point them to these URLs:
/llms.txt
Get a high-level, structured markdown summary of the entire Index Alpha API, perfect for priming LLM system contexts.
/llms-full.txt
Get the full API documentation, schemas, limits, and examples in a single, continuous markdown file.
2. Copyable OpenAPI 3.0 Specification
To integrate Index Alpha with modern agentic platforms like ChatGPT Actions, Claude Projects Custom Tools, or agent frameworks (such as CrewAI, AutoGen, and Vercel AI SDK), copy this OpenAPI 3.0 schema:
openapi: 3.0.3
info:
title: Index Alpha API
description: Premium Indonesian Stock Exchange (IDX) broker summary analytics API.
version: 1.0.0
servers:
- url: https://api.indexalpha.id/
paths:
/stocks/broker-summary:
get:
summary: Retrieve Broker Summary
description: Retrieve aggregated daily activity for brokers on a specific stock ticker. Records are updated every trading day at 12:00 GMT (19:00 Jakarta time). Historical data is available starting from 2025-01-01.
parameters:
- name: ticker
in: query
required: true
description: Stock ticker symbol (e.g., BBCA, TLKM)
schema:
type: string
- name: from
in: query
required: true
description: Start date in YYYY-MM-DD format (2025-01-01 or later)
schema:
type: string
format: date
- name: to
in: query
required: true
description: End date in YYYY-MM-DD format
schema:
type: string
format: date
- name: investor
in: query
required: true
description: Type of investor to aggregate.
schema:
type: string
enum: [all, f, d]
responses:
'200':
description: Successful response containing broker summary data.
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
data:
type: array
items:
type: object
properties:
code:
type: string
description: Broker code (e.g., SQ, AK, CC)
buy_freq:
type: integer
description: Number of buy transactions
buy_volume:
type: integer
description: Total share volume purchased
buy_value:
type: number
description: Total transaction value of purchases (in IDR)
sell_freq:
type: integer
description: Number of sell transactions
sell_volume:
type: integer
description: Total share volume sold
sell_value:
type: number
description: Total transaction value of sales (in IDR)
buy_avg:
type: number
description: Weighted average buy price
sell_avg:
type: number
description: Weighted average sell price
error:
type: string
nullable: true
'400':
description: Bad Request. Invalid parameters (e.g., dates before coverage start or a range longer than 366 days).
'401':
description: Unauthorized. Missing or invalid Bearer token.
'403':
description: Forbidden. Monthly or daily quota exhausted.
'422':
description: Validation error on the request parameters.
'429':
description: Too Many Requests. Rate limit exceeded.
'500':
description: Internal server error.
/stocks/broker-summary/batch:
post:
summary: Batch Broker Summary
description: Retrieve aggregated broker activity for multiple stock tickers in a single request.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
tickers:
type: array
items:
type: string
description: List of stock tickers (e.g., ["BBCA", "TLKM"]). Min 1, Max 50.
from:
type: string
format: date
description: Start date in YYYY-MM-DD format
to:
type: string
format: date
description: End date in YYYY-MM-DD format
investor:
type: string
enum: [all, f, d]
description: Investor type (default all)
market:
type: string
enum: [RG, NG, ALL]
description: Market segment (default RG)
required: [tickers, from, to]
responses:
'200':
description: Successful response containing broker summary data for each ticker.
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
data:
type: object
additionalProperties:
type: array
items:
type: object
properties:
code:
type: string
buy_freq:
type: integer
buy_volume:
type: integer
buy_value:
type: number
sell_freq:
type: integer
sell_volume:
type: integer
sell_value:
type: number
buy_avg:
type: number
sell_avg:
type: number
error:
type: string
nullable: true
'400':
description: Bad Request. Invalid parameters (e.g., dates before coverage start or a range longer than 366 days).
'401':
description: Unauthorized. Missing or invalid Bearer token.
'403':
description: Forbidden. Monthly or daily quota exhausted.
'422':
description: Validation error on the request parameters.
'429':
description: Too Many Requests. Rate limit exceeded.
'500':
description: Internal server error.
/foreign-flow:
get:
summary: Get Foreign Flow
description: Returns aggregated foreign buy, sell, and net trading activity for a stock ticker over a date range. Aggregated across all foreign brokers.
parameters:
- name: ticker
in: query
required: true
description: Stock ticker symbol (e.g., BBCA, TLKM)
schema:
type: string
- name: from
in: query
required: true
description: Start date in YYYY-MM-DD format
schema:
type: string
format: date
- name: to
in: query
required: true
description: End date in YYYY-MM-DD format
schema:
type: string
format: date
- name: market
in: query
required: false
description: Market segment (RG, NG, ALL). Default ALL.
schema:
type: string
enum: [ALL, RG, NG]
responses:
'200':
description: Successful response containing foreign flow data.
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
data:
type: object
properties:
foreign_buy:
type: integer
description: Total foreign buy transaction value (IDR)
foreign_sell:
type: integer
description: Total foreign sell transaction value (IDR)
net_foreign:
type: integer
description: Net foreign flow (foreign_buy - foreign_sell)
error:
type: string
nullable: true
'400':
description: Bad Request. Invalid parameters (e.g., dates before coverage start or a range longer than 366 days).
'401':
description: Unauthorized. Missing or invalid Bearer token.
'403':
description: Forbidden. Monthly or daily quota exhausted.
'422':
description: Validation error on the request parameters.
'429':
description: Too Many Requests. Rate limit exceeded.
'500':
description: Internal server error.
/foreign-flow/batch:
post:
summary: Batch Foreign Flow
description: Retrieve aggregated foreign flow for multiple stock tickers in a single request.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
tickers:
type: array
items:
type: string
description: List of stock tickers (e.g., ["BBCA", "TLKM"]). Min 1, Max 50.
from:
type: string
format: date
description: Start date in YYYY-MM-DD format
to:
type: string
format: date
description: End date in YYYY-MM-DD format
market:
type: string
enum: [ALL, RG, NG]
description: Market segment (default ALL)
required: [tickers, from, to]
responses:
'200':
description: Successful response containing foreign flow data for each ticker.
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
data:
type: object
additionalProperties:
type: object
properties:
foreign_buy:
type: integer
foreign_sell:
type: integer
net_foreign:
type: integer
error:
type: string
nullable: true
'400':
description: Bad Request. Invalid parameters (e.g., dates before coverage start or a range longer than 366 days).
'401':
description: Unauthorized. Missing or invalid Bearer token.
'403':
description: Forbidden. Monthly or daily quota exhausted.
'422':
description: Validation error on the request parameters.
'429':
description: Too Many Requests. Rate limit exceeded.
'500':
description: Internal server error.
/usage:
get:
summary: Check Usage & Limits
description: Monitor your active monthly call usage, current remaining quota, and reset date.
responses:
'200':
description: Successful response containing usage metrics.
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
data:
type: object
properties:
api_key:
type: string
description: Masked version of the active API key
monthly_limit:
type: integer
description: Total monthly quota allowed
current_usage:
type: integer
description: Number of API calls consumed this period
remaining:
type: integer
description: Number of API calls remaining in active quota
reset_date:
type: string
format: date-time
description: The timestamp when the quota resets
error:
type: string
nullable: true
'400':
description: Bad Request. Invalid parameters (e.g., dates before coverage start or a range longer than 366 days).
'401':
description: Unauthorized. Missing or invalid Bearer token.
'403':
description: Forbidden. Monthly or daily quota exhausted.
'422':
description: Validation error on the request parameters.
'429':
description: Too Many Requests. Rate limit exceeded.
'500':
description: Internal server error.
/news:
get:
summary: Get Market News
description: Fetches the latest articles from Indonesian market news RSS feeds and returns them grouped by source, newest first within each source. Articles are fetched live from the publisher feeds with a short 30s cache; a temporarily unreachable source is skipped.
responses:
'200':
description: Successful response containing per-source news articles.
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
data:
type: object
additionalProperties:
type: array
items:
type: object
properties:
source:
type: string
title:
type: string
description:
type: string
link:
type: string
image_url:
type: string
guid:
type: string
nullable: true
published_date:
type: string
format: date-time
nullable: true
error:
type: string
nullable: true
'401':
description: Unauthorized. Missing or invalid Bearer token.
'403':
description: Forbidden. Monthly or daily quota exhausted.
'429':
description: Too Many Requests. Rate limit exceeded.
'500':
description: Internal server error.
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
security:
- bearerAuth: []{
"openapi": "3.0.3",
"info": {
"title": "Index Alpha API",
"description": "Premium Indonesian Stock Exchange (IDX) broker summary analytics API.",
"version": "1.0.0"
},
"servers": [
{
"url": "https://api.indexalpha.id/"
}
],
"paths": {
"/stocks/broker-summary": {
"get": {
"summary": "Retrieve Broker Summary",
"description": "Retrieve aggregated daily activity for brokers on a specific stock ticker. Records are updated every trading day at 12:00 GMT (19:00 Jakarta time). Historical data is available starting from 2025-01-01.",
"parameters": [
{
"name": "ticker",
"in": "query",
"required": true,
"description": "Stock ticker symbol (e.g., BBCA, TLKM)",
"schema": {
"type": "string"
}
},
{
"name": "from",
"in": "query",
"required": true,
"description": "Start date in YYYY-MM-DD format (2025-01-01 or later)",
"schema": {
"type": "string",
"format": "date"
}
},
{
"name": "to",
"in": "query",
"required": true,
"description": "End date in YYYY-MM-DD format",
"schema": {
"type": "string",
"format": "date"
}
},
{
"name": "investor",
"in": "query",
"required": true,
"description": "Type of investor to aggregate.",
"schema": {
"type": "string",
"enum": ["all", "f", "d"]
}
}
],
"responses": {
"200": {
"description": "Successful response containing broker summary data.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "Broker code (e.g., SQ, AK, CC)"
},
"buy_freq": {
"type": "integer",
"description": "Number of buy transactions"
},
"buy_volume": {
"type": "integer",
"description": "Total share volume purchased"
},
"buy_value": {
"type": "number",
"description": "Total transaction value of purchases (in IDR)"
},
"sell_freq": {
"type": "integer",
"description": "Number of sell transactions"
},
"sell_volume": {
"type": "integer",
"description": "Total share volume sold"
},
"sell_value": {
"type": "number",
"description": "Total transaction value of sales (in IDR)"
},
"buy_avg": {
"type": "number",
"description": "Weighted average buy price"
},
"sell_avg": {
"type": "number",
"description": "Weighted average sell price"
}
}
}
},
"error": {
"type": "string",
"nullable": true
}
}
}
}
}
},
"400": { "description": "Bad Request. Invalid parameters (e.g., dates before coverage start or a range longer than 366 days)." },
"401": {
"description": "Unauthorized. Missing or invalid Bearer token."
},
"403": { "description": "Forbidden. Monthly or daily quota exhausted." },
"422": { "description": "Validation error on the request parameters." },
"429": {
"description": "Too Many Requests. Rate limit exceeded."
},
"500": { "description": "Internal server error." }
}
}
},
"/stocks/broker-summary/batch": {
"post": {
"summary": "Batch Broker Summary",
"description": "Retrieve aggregated broker activity for multiple stock tickers in a single request.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"tickers": {
"type": "array",
"items": { "type": "string" },
"description": "List of stock tickers (e.g. [\"BBCA\", \"TLKM\"]). Min 1, Max 50."
},
"from": { "type": "string", "format": "date", "description": "Start date in YYYY-MM-DD format" },
"to": { "type": "string", "format": "date", "description": "End date in YYYY-MM-DD format" },
"investor": { "type": "string", "enum": ["all", "f", "d"], "description": "Investor type (default all)" },
"market": { "type": "string", "enum": ["RG", "NG", "ALL"], "description": "Market segment (default RG)" }
},
"required": ["tickers", "from", "to"]
}
}
}
},
"responses": {
"200": {
"description": "Successful response containing broker summary data for each ticker.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": { "type": "boolean" },
"data": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": { "type": "string" },
"buy_freq": { "type": "integer" },
"buy_volume": { "type": "integer" },
"buy_value": { "type": "number" },
"sell_freq": { "type": "integer" },
"sell_volume": { "type": "integer" },
"sell_value": { "type": "number" },
"buy_avg": { "type": "number" },
"sell_avg": { "type": "number" }
}
}
}
},
"error": { "type": "string", "nullable": true }
}
}
}
}
},
"400": { "description": "Bad Request. Invalid parameters (e.g., dates before coverage start or a range longer than 366 days)." },
"401": { "description": "Unauthorized. Missing or invalid Bearer token." },
"403": { "description": "Forbidden. Monthly or daily quota exhausted." },
"422": { "description": "Validation error on the request parameters." },
"429": { "description": "Too Many Requests. Rate limit exceeded." },
"500": { "description": "Internal server error." }
}
}
},
"/foreign-flow": {
"get": {
"summary": "Get Foreign Flow",
"description": "Returns aggregated foreign buy, sell, and net trading activity for a stock ticker over a date range. Aggregated across all foreign brokers.",
"parameters": [
{
"name": "ticker",
"in": "query",
"required": true,
"description": "Stock ticker symbol (e.g., BBCA, TLKM)",
"schema": { "type": "string" }
},
{
"name": "from",
"in": "query",
"required": true,
"description": "Start date in YYYY-MM-DD format",
"schema": { "type": "string", "format": "date" }
},
{
"name": "to",
"in": "query",
"required": true,
"description": "End date in YYYY-MM-DD format",
"schema": { "type": "string", "format": "date" }
},
{
"name": "market",
"in": "query",
"required": false,
"description": "Market segment (RG, NG, ALL). Default ALL.",
"schema": { "type": "string", "enum": ["ALL", "RG", "NG"] }
}
],
"responses": {
"200": {
"description": "Successful response containing foreign flow data.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": { "type": "boolean" },
"data": {
"type": "object",
"properties": {
"foreign_buy": { "type": "integer", "description": "Total foreign buy transaction value (IDR)" },
"foreign_sell": { "type": "integer", "description": "Total foreign sell transaction value (IDR)" },
"net_foreign": { "type": "integer", "description": "Net foreign flow (foreign_buy - foreign_sell)" }
}
},
"error": { "type": "string", "nullable": true }
}
}
}
}
},
"400": { "description": "Bad Request. Invalid parameters (e.g., dates before coverage start or a range longer than 366 days)." },
"401": { "description": "Unauthorized. Missing or invalid Bearer token." },
"403": { "description": "Forbidden. Monthly or daily quota exhausted." },
"422": { "description": "Validation error on the request parameters." },
"429": { "description": "Too Many Requests. Rate limit exceeded." },
"500": { "description": "Internal server error." }
}
}
},
"/foreign-flow/batch": {
"post": {
"summary": "Batch Foreign Flow",
"description": "Retrieve aggregated foreign flow for multiple stock tickers in a single request.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"tickers": {
"type": "array",
"items": { "type": "string" },
"description": "List of stock tickers (e.g. [\"BBCA\", \"TLKM\"]). Min 1, Max 50."
},
"from": { "type": "string", "format": "date", "description": "Start date in YYYY-MM-DD format" },
"to": { "type": "string", "format": "date", "description": "End date in YYYY-MM-DD format" },
"market": { "type": "string", "enum": ["ALL", "RG", "NG"], "description": "Market segment (default ALL)" }
},
"required": ["tickers", "from", "to"]
}
}
}
},
"responses": {
"200": {
"description": "Successful response containing foreign flow data for each ticker.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": { "type": "boolean" },
"data": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"foreign_buy": { "type": "integer" },
"foreign_sell": { "type": "integer" },
"net_foreign": { "type": "integer" }
}
}
},
"error": { "type": "string", "nullable": true }
}
}
}
}
},
"400": { "description": "Bad Request. Invalid parameters (e.g., dates before coverage start or a range longer than 366 days)." },
"401": { "description": "Unauthorized. Missing or invalid Bearer token." },
"403": { "description": "Forbidden. Monthly or daily quota exhausted." },
"422": { "description": "Validation error on the request parameters." },
"429": { "description": "Too Many Requests. Rate limit exceeded." },
"500": { "description": "Internal server error." }
}
}
},
"/usage": {
"get": {
"summary": "Check Usage & Limits",
"description": "Monitor your active monthly call usage, current remaining quota, and reset date.",
"responses": {
"200": {
"description": "Successful response containing usage metrics.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"type": "object",
"properties": {
"api_key": {
"type": "string",
"description": "Masked version of the active API key"
},
"monthly_limit": {
"type": "integer",
"description": "Total monthly quota allowed"
},
"current_usage": {
"type": "integer",
"description": "Number of API calls consumed this period"
},
"remaining": {
"type": "integer",
"description": "Number of API calls remaining in active quota"
},
"reset_date": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the quota resets"
}
}
},
"error": {
"type": "string",
"nullable": true
}
}
}
}
}
},
"400": { "description": "Bad Request. Invalid parameters (e.g., dates before coverage start or a range longer than 366 days)." },
"401": {
"description": "Unauthorized. Missing or invalid Bearer token."
},
"403": { "description": "Forbidden. Monthly or daily quota exhausted." },
"422": { "description": "Validation error on the request parameters." },
"429": {
"description": "Too Many Requests. Rate limit exceeded."
},
"500": { "description": "Internal server error." }
}
}
},
"/news": {
"get": {
"summary": "Get Market News",
"description": "Fetches the latest articles from Indonesian market news RSS feeds and returns them grouped by source, newest first within each source. Articles are fetched live from the publisher feeds with a short 30s cache; a temporarily unreachable source is skipped.",
"responses": {
"200": {
"description": "Successful response containing per-source news articles.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": { "type": "boolean" },
"data": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "object",
"properties": {
"source": { "type": "string" },
"title": { "type": "string" },
"description": { "type": "string" },
"link": { "type": "string" },
"image_url": { "type": "string" },
"guid": { "type": "string", "nullable": true },
"published_date": { "type": "string", "format": "date-time", "nullable": true }
}
}
}
},
"error": { "type": "string", "nullable": true }
}
}
}
}
},
"401": { "description": "Unauthorized. Missing or invalid Bearer token." },
"403": { "description": "Forbidden. Monthly or daily quota exhausted." },
"429": { "description": "Too Many Requests. Rate limit exceeded." },
"500": { "description": "Internal server error." }
}
}
}
},
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
},
"security": [
{
"bearerAuth": []
}
]
}3. Cursor Rules & Copilot Instructions
If you use AI-powered IDEs like Cursor, Windsurf, or VS Code Copilot, copy the following ruleset and save it to .cursorrules or .github/copilot-instructions.md in your project root.
This ensures that whenever you ask the AI to generate stock tracking, trading analysis, or broker accumulation components, it writes flawless, type-safe code compatible with Index Alpha:
# Index Alpha API Integration Guidelines
You are an expert developer building an integration with the Index Alpha API, which provides premium Indonesian Stock Exchange (IDX) broker summary analytics.
## API Architecture Reference
- Base URL: `https://api.indexalpha.id/`
- Authorization: Bearer Token required on all requests in the header: `Authorization: Bearer <token>`
## Available Endpoints
### 1. Retrieve Broker Summary (`GET /stocks/broker-summary`)
Returns daily broker transaction summaries for a stock ticker.
- **Parameters:**
- `ticker` (string, required): Stock ticker symbol (e.g., `BBCA`, `TLKM`)
- `from` (string, required, YYYY-MM-DD): Start date (2025-01-01 or later)
- `to` (string, required, YYYY-MM-DD): End date
- `investor` (string, required): One of `all`, `f` (foreign), `d` (domestic)
- **Output:** Returns an array of broker records with:
- `code` (broker initials), `buy_freq`, `buy_volume`, `buy_value`, `sell_freq`, `sell_volume`, `sell_value`, `buy_avg` (weighted price), `sell_avg`
### 2. Batch Broker Summary (`POST /stocks/broker-summary/batch`)
Returns aggregated broker activity for multiple stock tickers.
- **Body:**
- `tickers` (array[string], required): Stock tickers (e.g., `["BBCA", "TLKM"]`)
- `from` (string, required, YYYY-MM-DD): Start date
- `to` (string, required, YYYY-MM-DD): End date
- `investor` (string, optional): One of `all`, `f`, `d`
- `market` (string, optional): One of `RG`, `NG`, `ALL`
### 3. Foreign Flow (`GET /foreign-flow`)
Returns aggregated foreign buy, sell, and net trading activity for a stock ticker.
- **Parameters:**
- `ticker` (string, required): Stock ticker symbol (e.g., `BBCA`, `TLKM`)
- `from` (string, required, YYYY-MM-DD): Start date
- `to` (string, required, YYYY-MM-DD): End date
- `market` (string, optional): One of `ALL`, `RG`, `NG` (default `ALL`)
### 4. Batch Foreign Flow (`POST /foreign-flow/batch`)
Returns aggregated foreign flow for multiple stock tickers.
- **Body:**
- `tickers` (array[string], required): Stock tickers (e.g., `["BBCA", "TLKM"]`)
- `from` (string, required, YYYY-MM-DD): Start date
- `to` (string, required, YYYY-MM-DD): End date
- `market` (string, optional): One of `ALL`, `RG`, `NG`
### 5. Check Usage and Quotas (`GET /usage`)
Returns API quota status. Highly recommended to run periodically to avoid rate limits or exhaustion.
- **Output:** Returns `monthly_limit`, `current_usage`, `remaining`, `reset_date`.
### 6. Market News (`GET /news`)
Fetches the latest articles from Indonesian market news RSS feeds, grouped by source.
- **Parameters:** none
- **Output:** Returns an object mapping each source name to a newest-first array of articles with `source`, `title`, `description`, `link`, `image_url`, `guid`, `published_date`.
## Code Conventions (TypeScript)
Use the following strict types when building integrations:
```typescript
export interface BrokerSummaryRecord {
code: string;
buy_freq: number;
buy_volume: number;
buy_value: number;
sell_freq: number;
sell_volume: number;
sell_value: number;
buy_avg: number;
sell_avg: number;
}
export interface ApiResponse<T> {
success: boolean;
data: T;
error: string | null;
}
export interface UsageData {
api_key: string;
monthly_limit: number;
current_usage: number;
remaining: number;
reset_date: string;
}
export interface BatchBrokerSummaryRequest {
tickers: string[];
from: string;
to: string;
investor?: string;
market?: string;
}
export interface ForeignFlowData {
foreign_buy: number;
foreign_sell: number;
net_foreign: number;
}
export interface BatchForeignFlowRequest {
tickers: string[];
from: string;
to: string;
market?: string;
}
```
## Critical Integration Tips
- **Trading Schedule**: Broker summaries only provide Regular Market records. The metrics are refreshed once daily at 12:00 GMT (19:00 Jakarta / WIB time) on active trading days.
- **Error & Quota Handling**:
- Catch `401 Unauthorized` for key validation issues.
- Catch `429 Too Many Requests` when limits are reached. Free tier is strictly limited to 10 requests per minute and 5 per day. Check remaining quota via `/usage`.
- **Performance**: Cache broker summary results for a specific ticker + date range. The data is historical and static after the daily refresh, meaning there is no need to make repeated API calls for the same parameters.4. Standard LLM Tool Call Formats (JSON Schema)
When integrating Index Alpha directly into codebases using the OpenAI Node/Python SDKs, LangChain, or Vercel AI SDK, you can pass these exact tool definitions directly to the model:
[
{
"type": "function",
"function": {
"name": "get_broker_summary",
"description": "Retrieves the aggregated daily activity and transaction summaries for stock brokers on a specific Indonesian Stock Exchange (IDX) stock ticker for a date range.",
"parameters": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "The stock ticker symbol (e.g., BBCA, TLKM, ASII)."
},
"from": {
"type": "string",
"description": "Start date in YYYY-MM-DD format. Data begins 2025-01-01."
},
"to": {
"type": "string",
"description": "End date in YYYY-MM-DD format."
},
"investor": {
"type": "string",
"enum": ["all", "f", "d"],
"description": "Filter by investor type: 'all', 'f' (foreign), 'd' (domestic)."
}
},
"required": ["ticker", "from", "to", "investor"]
}
}
},
{
"type": "function",
"function": {
"name": "get_api_usage",
"description": "Checks the active API key monthly call limits, current usage, and remaining quota for the Index Alpha API.",
"parameters": {
"type": "object",
"properties": {}
}
}
},
{
"type": "function",
"function": {
"name": "get_foreign_flow",
"description": "Returns aggregated foreign buy, sell, and net trading activity for a stock ticker over a date range.",
"parameters": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "The stock ticker symbol (e.g., BBCA, TLKM)."
},
"from": {
"type": "string",
"description": "Start date in YYYY-MM-DD format."
},
"to": {
"type": "string",
"description": "End date in YYYY-MM-DD format."
},
"market": {
"type": "string",
"enum": ["ALL", "RG", "NG"],
"description": "Market segment: RG, NG, or ALL (default)."
}
},
"required": ["ticker", "from", "to"]
}
}
},
{
"type": "function",
"function": {
"name": "get_broker_summary_batch",
"description": "Retrieve aggregated broker activity for multiple stock tickers in a single request.",
"parameters": {
"type": "object",
"properties": {
"tickers": {
"type": "array",
"items": { "type": "string" },
"description": "Array of stock tickers (e.g., [\"BBCA\", \"TLKM\"]). Min 1, Max 50."
},
"from": { "type": "string", "description": "Start date in YYYY-MM-DD format." },
"to": { "type": "string", "description": "End date in YYYY-MM-DD format." },
"investor": {
"type": "string",
"enum": ["all", "f", "d"],
"description": "Investor type: all (default), f (foreign), d (domestic)."
},
"market": {
"type": "string",
"enum": ["RG", "NG", "ALL"],
"description": "Market segment: RG (default), NG, or ALL."
}
},
"required": ["tickers", "from", "to"]
}
}
},
{
"type": "function",
"function": {
"name": "get_foreign_flow_batch",
"description": "Retrieve aggregated foreign flow for multiple stock tickers in a single request.",
"parameters": {
"type": "object",
"properties": {
"tickers": {
"type": "array",
"items": { "type": "string" },
"description": "Array of stock tickers (e.g., [\"BBCA\", \"TLKM\"]). Min 1, Max 50."
},
"from": { "type": "string", "description": "Start date in YYYY-MM-DD format." },
"to": { "type": "string", "description": "End date in YYYY-MM-DD format." },
"market": {
"type": "string",
"enum": ["ALL", "RG", "NG"],
"description": "Market segment: ALL (default), RG, or NG."
}
},
"required": ["tickers", "from", "to"]
}
}
}
]Here is how you execute these tools in your backend when the model triggers a function call:
import axios from 'axios';
const INDEX_ALPHA_API_KEY = process.env.INDEX_ALPHA_API_KEY;
const client = axios.create({
baseURL: 'https://api.indexalpha.id',
headers: {
'Authorization': `Bearer ${INDEX_ALPHA_API_KEY}`,
'Accept': 'application/json',
}
});
export async function handleToolCall(name: string, args: any) {
switch (name) {
case 'get_broker_summary':
const { ticker, from, to, investor } = args;
const summaryRes = await client.get('/stocks/broker-summary', {
params: { ticker, from, to, investor }
});
return summaryRes.data;
case 'get_api_usage':
const usageRes = await client.get('/usage');
return usageRes.data;
case 'get_foreign_flow':
const { ticker: ffTicker, from: ffFrom, to: ffTo, market: ffMarket } = args;
const ffRes = await client.get('/foreign-flow', {
params: { ticker: ffTicker, from: ffFrom, to: ffTo, market: ffMarket || 'ALL' }
});
return ffRes.data;
case 'get_broker_summary_batch':
const bsRes = await client.post('/stocks/broker-summary/batch', args);
return bsRes.data;
case 'get_foreign_flow_batch':
const ffbRes = await client.post('/foreign-flow/batch', args);
return ffbRes.data;
default:
throw new Error(`Unknown tool: ${name}`);
}
}5. Expose as a Model Context Protocol (MCP) Server
Model Context Protocol (MCP) is the open standard designed by Anthropic for exposing tools and resources directly to LLM clients (like Claude Desktop, Cursor, or IDE extensions).
By running a local MCP server, an AI assistant can seamlessly query IDX broker summaries in real time to answer analytical user prompts.
Prefer not to run a local server? Connect directly to our hosted endpoint instead. See the Remote MCP Connection guide.
Here is a ready-to-run, single-file Node.js MCP Server implementation using the official SDK.
Step 1: Create the Server File
Create a file named index-alpha-mcp.js and install the dependency:
npm install @modelcontextprotocol/sdkSave this code inside index-alpha-mcp.js:
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import fetch from "node-fetch";
const API_KEY = process.env.INDEX_ALPHA_API_KEY;
if (!API_KEY) {
console.error("Error: INDEX_ALPHA_API_KEY environment variable is required.");
process.exit(1);
}
const server = new Server(
{
name: "index-alpha-mcp-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// Register Tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "get_broker_summary",
description: "Fetch Indonesian Stock Exchange (IDX) broker daily accumulations and transaction activity for a ticker.",
inputSchema: {
type: "object",
properties: {
ticker: { type: "string", description: "Stock symbol (e.g. BBCA, TLKM)" },
from: { type: "string", description: "Start date YYYY-MM-DD (historical starting 2025-01-01)" },
to: { type: "string", description: "End date YYYY-MM-DD" },
investor: { type: "string", enum: ["all", "f", "d"], description: "Investor group filter" },
},
required: ["ticker", "from", "to", "investor"],
},
},
{
name: "get_usage_limits",
description: "Check active Index Alpha API quota usage and remaining limits.",
inputSchema: { type: "object", properties: {} },
},
{
name: "get_foreign_flow",
description: "Get aggregated foreign buy, sell, and net trading activity for a stock ticker over a date range.",
inputSchema: {
type: "object",
properties: {
ticker: { type: "string", description: "Stock symbol (e.g. BBCA, TLKM)" },
from: { type: "string", description: "Start date YYYY-MM-DD" },
to: { type: "string", description: "End date YYYY-MM-DD" },
market: { type: "string", enum: ["ALL", "RG", "NG"], description: "Market segment (default ALL)" },
},
required: ["ticker", "from", "to"],
},
},
{
name: "get_broker_summary_batch",
description: "Retrieve aggregated broker activity for multiple stock tickers in a single request.",
inputSchema: {
type: "object",
properties: {
tickers: { type: "array", items: { type: "string" }, description: "Array of stock tickers (e.g. [\"BBCA\", \"TLKM\"]). Min 1, Max 50." },
from: { type: "string", description: "Start date YYYY-MM-DD" },
to: { type: "string", description: "End date YYYY-MM-DD" },
investor: { type: "string", enum: ["all", "f", "d"], description: "Investor type (default all)" },
market: { type: "string", enum: ["RG", "NG", "ALL"], description: "Market segment (default RG)" },
},
required: ["tickers", "from", "to"],
},
},
{
name: "get_foreign_flow_batch",
description: "Retrieve aggregated foreign flow for multiple stock tickers in a single request.",
inputSchema: {
type: "object",
properties: {
tickers: { type: "array", items: { type: "string" }, description: "Array of stock tickers (e.g. [\"BBCA\", \"TLKM\"]). Min 1, Max 50." },
from: { type: "string", description: "Start date YYYY-MM-DD" },
to: { type: "string", description: "End date YYYY-MM-DD" },
market: { type: "string", enum: ["ALL", "RG", "NG"], description: "Market segment (default ALL)" },
},
required: ["tickers", "from", "to"],
},
},
],
};
});
// Handle Tool Calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
if (name === "get_broker_summary") {
const url = `https://api.indexalpha.id/stocks/broker-summary?ticker=${args.ticker}&from=${args.from}&to=${args.to}&investor=${args.investor}`;
const response = await fetch(url, {
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Accept": "application/json"
}
});
const data = await response.json();
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
} else if (name === "get_usage_limits") {
const response = await fetch("https://api.indexalpha.id/usage", {
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Accept": "application/json"
}
});
const data = await response.json();
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
} else if (name === "get_foreign_flow") {
const params = new URLSearchParams({
ticker: args.ticker,
from: args.from,
to: args.to,
});
if (args.market) params.append("market", args.market);
const response = await fetch(`https://api.indexalpha.id/foreign-flow?${params}`, {
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Accept": "application/json"
}
});
const data = await response.json();
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
} else if (name === "get_broker_summary_batch") {
const response = await fetch("https://api.indexalpha.id/stocks/broker-summary/batch", {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify(args)
});
const data = await response.json();
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
} else if (name === "get_foreign_flow_batch") {
const response = await fetch("https://api.indexalpha.id/foreign-flow/batch", {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify(args)
});
const data = await response.json();
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
} else {
throw new Error(`Tool not found: ${name}`);
}
} catch (error) {
return {
isError: true,
content: [{ type: "text", text: error.message }],
};
}
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Index Alpha MCP Server running on stdio");
}
main().catch((err) => {
console.error("Fatal error:", err);
process.exit(1);
});Step 2: Configure Your LLM Client (e.g. Claude Desktop)
To use the server with Claude Desktop, add it to your configuration file (typically at AppData\Roaming\Claude\claude_desktop_config.json on Windows or ~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"index-alpha": {
"command": "node",
"args": ["/path/to/index-alpha-mcp.js"],
"env": {
"INDEX_ALPHA_API_KEY": "YOUR_ACTUAL_API_KEY"
}
}
}
}Restart Claude Desktop, and your assistant will be able to query live broker summary data directly in conversation!