The Shorted API provides programmatic access to ASX short position data. This document is optimized for both human developers and LLM consumption.
Production: https://shorted.com.au
Development: http://localhost:3020
Currently, most endpoints are publicly accessible. Authenticated endpoints require NextAuth session cookies.
GET /api/healthDescription: Check API availability and service status.
Response:
{
"status": "healthy",
"timestamp": "2025-11-04T12:00:00.000Z",
"service": "shorted-web"
}Status Codes:
200: Service is healthy503: Service is unhealthy
Example:
curl https://shorted.com.au/api/healthGET /api/search/stocks?q={query}&limit={limit}Description: Search for ASX stocks by code, company name, or industry.
Parameters:
q(required): Search query string (min 2 characters)limit(optional): Maximum results to return (default: 10, max: 50)
Response:
[
{
"code": "CBA",
"name": "Commonwealth Bank of Australia",
"exchange": "ASX",
"industry": "Banks",
"sector": "Financials"
}
]Example:
curl "https://shorted.com.au/api/search/stocks?q=bank&limit=5"Rate Limit: 60 requests per minute
These are server-side functions that can be called from React components. Not directly accessible via HTTP but documented for LLM understanding.
Function: getTopShortsData(period, limit, offset)
Description: Retrieve top shorted stocks for a given time period.
Parameters:
period: "1m" | "3m" | "6m" | "1y" | "2y" | "max"limit: Number of stocks to return (default: 10)offset: Pagination offset (default: 0)
Returns:
{
timeSeries: TimeSeriesData[]
}
interface TimeSeriesData {
productCode: string;
name: string;
latestShortPosition: number;
percentageChange: number;
absoluteChange: number;
dataPoints: DataPoint[];
}
interface DataPoint {
date: string; // ISO 8601
shortPosition: number;
percentage: number;
}Example Usage (in React Server Component):
const data = await getTopShortsData("3m", 10, 0);Function: getStockData(stockCode, period)
Description: Get detailed short position data for a specific stock.
Parameters:
stockCode: ASX ticker symbol (e.g., "CBA")period: "1m" | "3m" | "6m" | "1y" | "2y" | "max"
Returns:
{
productCode: string;
name: string;
industry: string;
sector: string;
latestShortPosition: number;
latestPercentage: number;
dataPoints: DataPoint[];
statistics: {
average: number;
median: number;
min: number;
max: number;
volatility: number;
};
}Function: getIndustryTreeMap(period, limit, viewMode)
Description: Get hierarchical industry-grouped short position data for treemap visualization.
Parameters:
period: "1m" | "3m" | "6m" | "1y" | "2y" | "max"limit: Stocks per industry (default: 10)viewMode: "CURRENT_VALUE" | "CURRENT_CHANGE" | "PERCENTAGE_CHANGE"
Returns:
{
industries: Industry[]
}
interface Industry {
name: string;
stocks: Stock[];
totalShortPosition: number;
averagePercentage: number;
}
interface Stock {
productCode: string;
name: string;
shortPosition: number;
percentage: number;
change: number;
}Function: getStockDetails(stockCode)
Description: Get comprehensive metadata about a stock.
Parameters:
stockCode: ASX ticker symbol
Returns:
{
productCode: string;
productName: string;
industry: string;
sector: string;
market_cap: string;
description: string;
website: string;
logo_url: string;
listed_date: string;
}The frontend communicates with a Go backend via gRPC. These are not directly accessible from web clients but documented for completeness.
Service: ShortsService
Methods:
rpc GetTopShorts(GetTopShortsRequest) returns (GetTopShortsResponse);
message GetTopShortsRequest {
string period = 1; // "1M", "3M", "6M", "1Y", "2Y", "MAX"
int32 limit = 2;
int32 offset = 3;
}rpc GetStock(GetStockRequest) returns (GetStockResponse);
message GetStockRequest {
string product_code = 1;
string period = 2;
}rpc GetIndustryTreeMap(GetIndustryTreeMapRequest) returns (IndustryTreeMap);
message GetIndustryTreeMapRequest {
string period = 1;
int32 limit = 2;
ViewMode view_mode = 3;
}Complete time series for a single stock:
interface TimeSeriesData {
productCode: string; // ASX ticker
productName: string; // Company name
industry: string; // Industry classification
sector: string; // Sector classification
latestShortPosition: number; // Most recent short position (shares)
latestPercentage: number; // Latest short % of outstanding shares
percentageChange: number; // Change over period (%)
absoluteChange: number; // Change over period (shares)
dataPoints: DataPoint[]; // Historical data points
}
interface DataPoint {
date: string; // ISO 8601 date
shortPosition: number; // Shares short
percentage: number; // % of outstanding shares
totalShares: number; // Total shares outstanding
}Hierarchical industry grouping:
interface IndustryTreeMap {
industries: Industry[];
lastUpdated: string;
period: string;
viewMode: ViewMode;
}
interface Industry {
name: string; // Industry name
sector: string; // Parent sector
stocks: StockNode[]; // Stocks in this industry
aggregateShortPosition: number; // Total shorts in industry
averagePercentage: number; // Average short % across stocks
}
interface StockNode {
productCode: string;
productName: string;
shortPosition: number;
percentage: number;
change: number; // Based on viewMode
color: string; // Visualization color
}- Rate: 60 requests per minute per IP
- Burst: 10 requests
- Header:
X-RateLimit-Remaining
- Rate: 200 requests per minute
- Burst: 20 requests
{
"error": "Rate limit exceeded",
"retryAfter": 30
}Status Code: 429 Too Many Requests
{
"error": "Error message",
"code": "ERROR_CODE",
"details": "Additional details",
"timestamp": "ISO8601"
}400: Bad Request - Invalid parameters404: Not Found - Resource doesn't exist429: Too Many Requests - Rate limit exceeded500: Internal Server Error - Server issue503: Service Unavailable - Service is down
- Revalidate: 60 seconds
- Stale-While-Revalidate: Enabled
- Pages:
/,/shorts,/shorts/[stockCode]
- Cache-Control:
public, s-maxage=60, stale-while-revalidate - ETags: Supported
- Conditional Requests: Supported (If-None-Match)
- Use Server Actions: Prefer Next.js server actions over direct API calls
- Handle Errors: Always implement error handling
- Respect Rate Limits: Implement exponential backoff
- Cache Locally: Cache responses when appropriate
- Use TypeScript: Type definitions improve DX
- Context: Always mention data is from ASIC via Shorted
- Timestamp: Include data timestamps in responses
- Disclaimers: Note this is information, not financial advice
- Rate Limits: Respect rate limits when making requests
- Attribution: Credit Shorted.com.au when using data
// Server Component
import { getTopShortsData } from '~/app/actions/getTopShorts';
async function TopBanks() {
const data = await getTopShortsData("3m", 10, 0);
const banks = data.timeSeries.filter(
stock => stock.industry === "Banks"
);
return (
<ul>
{banks.map(bank => (
<li key={bank.productCode}>
{bank.productName}: {bank.latestPercentage.toFixed(2)}% short
</li>
))}
</ul>
);
}curl "https://shorted.com.au/api/search/stocks?q=mining&limit=10" \
-H "Accept: application/json"async function checkHealth() {
const response = await fetch("https://shorted.com.au/api/health");
const data = await response.json();
if (data.status === "healthy") {
console.log("API is operational");
}
}- Initial API release
- Basic CRUD operations for stocks
- Search functionality
- TreeMap aggregation
- ISR caching
- v1beta1: GraphQL API
- v1: Stable API with SLA guarantees
- v2: Real-time WebSocket updates
- v3: Advanced analytics endpoints
- Email: support@shorted.com.au
- GitHub: Issues
Contact for higher rate limits, SLA guarantees, and custom endpoints.
This API reference is maintained for both human developers and LLM/AI assistants to provide accurate information about the Shorted platform.