Build production-grade return forensics without rebuilding the finance logic stack.
The SDK and API are designed for teams that need raw prices, corporate actions, IPO assumptions, and value simulation to stay consistent across dashboards, workflows, and internal tooling.
Quickstart
Install the SDK, create a client, and run your first return-forensics request in minutes.
Install
Use the official npm package and keep your API key server-side for production apps.
npm install @arthalekh/sdkCreate a client
The SDK talks to the hosted Arthalekh API and returns typed envelopes with data, source, warning, and requestId.
import { createArthalekhClient } from '@arthalekh/sdk';
const client = createArthalekhClient({
apiKey: process.env.ARTHALEKH_API_KEY!,
});Run analysis
This returns the same core workflow your users see in the Arthalekh app: prices, actions, resolved IPO inputs, latest quote, and simulated portfolio output.
const result = await client.analysis.run({
symbol: 'WIPRO.NSE',
initialInvestment: 10000,
includeDividends: true,
});
console.log(result.data.simulation.finalValue);
console.log(result.data.actions.bonuses);Build a chart-ready bundle
If your frontend needs summary labels and precomputed markers immediately, use analysis.bundle(...) instead of composing that layer yourself.
const bundle = await client.analysis.bundle({
symbol: 'RELIANCE.NSE',
initialInvestment: 50000,
});
console.log(bundle.data.summary.finalValueLabel);
console.log(bundle.data.markers.price.dividends);Clean peer comparisons
Set includeStoredBonuses: false when you want comparisons to ignore manually stored bonus overrides and use only Arthalekh defaults plus any request-scoped manual bonuses.
const result = await client.analysis.run({
symbol: 'INFY.NSE',
initialInvestment: 10000,
includeStoredBonuses: false,
});
console.log(result.data.actions.bonuses);MCP Access
Expose Arthalekh content and live return-forensics through a public read-only MCP server.
Endpoint
Arthalekh publishes a remote MCP server at https://arthalekh.com/mcp.
It is intentionally read-only and designed for external clients that can speak MCP over HTTP.
Available tools
Use search to find relevant Arthalekh pages, guides, blog posts, developer docs, and stock methodology pages.
Use fetch to retrieve a full document body for a search result with its canonical URL for citations.
Use analyze_stock to run live action-aware stock analysis from the same underlying Arthalekh workflow used in the app.
Connection example
Use this server URL when connecting Arthalekh to any MCP-capable client.
{
"type": "url",
"name": "arthalekh",
"url": "https://arthalekh.com/mcp"
}Authentication
Authenticate with an Arthalekh API key and understand free vs pro behavior.
API keys
Send your key as Authorization: Bearer <key> or let the SDK do it for you.
Free keys are rate-limited more aggressively than Pro keys. Every successful response includes a requestId for support and debugging.
Raw REST example
You can call the HTTP API directly if you prefer your own client stack.
curl -X GET 'https://arthalekh.com/api/v1/prices?symbol=INFY.NSE' \
-H 'Authorization: Bearer YOUR_API_KEY'JavaScript SDK
Understand the SDK client methods, helper utilities, and chart-marker helpers.
Core methods
client.prices.get, client.actions.get, client.quote.get, client.metadata.get, client.metadata.upsert, client.bonuses.get, client.bonuses.replace, client.analysis.run, client.analysis.bundle, client.analysis.runMany, client.health.get, and client.openapi.get are all available from a single client instance.
client.openapi.get returns the raw OpenAPI document because the contract route is intentionally public and unwrapped.
Marker helpers for charts
Use the local chart-marker helpers when you want to plot dividends, splits, and bonuses on your own charting library.
import { buildPriceChartMarkers } from '@arthalekh/sdk';
const markers = buildPriceChartMarkers({
prices: result.data.prices,
dividends: result.data.actions.dividends,
splits: result.data.actions.splits,
bonuses: result.data.actions.bonuses,
});Batch analysis
Use runMany for portfolio screens, comparison tables, or internal research jobs that need multiple symbols in one pass.
const rows = await client.analysis.runMany(
[
{ symbol: 'INFY.NSE', initialInvestment: 10000 },
{ symbol: 'TCS.NSE', initialInvestment: 10000 },
{ symbol: 'WIPRO.NSE', initialInvestment: 10000 },
],
{ concurrency: 2 },
);
const successful = rows.filter((row) => row.ok);Infrastructure checks
Use the health surface in CI or internal tooling to verify that the API is up and cache-backed before a batch job starts.
const health = await client.health.get();
console.log(health.data.status);
console.log(health.data.cacheSymbols);REST API
Use the versioned HTTP API directly when you do not want a package dependency.
Base URL
All SDK-backed public endpoints live under https://arthalekh.com/api/v1.
OpenAPI
Use the live OpenAPI document for internal tooling, generated clients, or contract verification in CI.
curl -X GET 'https://arthalekh.com/api/v1/openapi.json'Health endpoint
Call the authenticated health endpoint to verify API availability, key validity, and cache readiness.
curl -X GET 'https://arthalekh.com/api/v1/health' \
-H 'Authorization: Bearer YOUR_API_KEY'Analysis Workflow
Understand how Arthalekh resolves IPO assumptions and computes value over time.
Resolution order
Explicit request inputs win first. If omitted, Arthalekh uses saved metadata, then internal IPO hints for known symbols, then the earliest available trading day in the loaded price series.
Bonus events are merged from stored manual bonuses, internal assumptions, and any manual bonuses passed in the request.
Simulation model
Shares begin as initialInvestment / ipoPrice.
Splits and bonuses change share count. Dividends add cash. Portfolio value is shares * close + cash on each trading day.
Server-assisted integration
For frontend apps, call your own backend route, invoke client.analysis.bundle there, and send only the minimal payload to the browser.
This is the same pattern Arthalekh uses for /app so the browser never needs a developer API key.
import { createArthalekhClient } from '@arthalekh/sdk';
const client = createArthalekhClient({
apiKey: process.env.ARTHALEKH_API_KEY!,
baseUrl: 'https://arthalekh.com/api/v1',
});
export async function POST(req: Request) {
const body = await req.json();
const bundle = await client.analysis.bundle({
symbol: body.symbol,
initialInvestment: body.initialInvestment,
includeDividends: body.includeDividends ?? true,
includeStoredBonuses: body.includeStoredBonuses ?? true,
});
return Response.json({
data: { bundle: bundle.data },
source: bundle.source,
warning: bundle.warning,
});
}Errors and Limits
Handle rate limits, demo fallbacks, and typed SDK errors safely.
Error model
The SDK throws ArthalekhApiError for non-2xx responses. It includes status, code, requestId, and retryable.
The source field in successful responses tells you whether results came from live API, cache, stale cache, demo fallback, or system metadata.
Handling failures
Treat source: demo and warning as product signals, not just transport details. They let you keep UX graceful when live providers are degraded.
import { ArthalekhApiError } from '@arthalekh/sdk';
try {
const result = await client.analysis.run({
symbol: 'INFY.NSE',
initialInvestment: 10000,
});
if (result.warning) {
console.warn(result.warning);
}
} catch (error) {
if (error instanceof ArthalekhApiError) {
console.error(error.code, error.status, error.requestId);
}
}OpenAPI access
The contract document is public and raw. You can fetch it through the SDK or hit the route directly in CI and codegen pipelines.
const openapi = await client.openapi.get();
console.log(openapi.openapi);
console.log(Object.keys(openapi.paths ?? {}));Changelog
Track the public SDK and API contract over time.
0.3.0
Fixes client.openapi.get so it returns the raw OpenAPI document instead of treating it like an envelope.
Adds includeStoredBonuses to the analysis input so app-style peer comparisons can intentionally ignore stored manual bonus overrides.
Documents the same server-side SDK bridge pattern used by Arthalekh /app.
0.2.0
Adds analysis.bundle and analysis.runMany for app-ready UI output and batch workflows.
Adds authenticated health checks, richer OpenAPI coverage, and upgraded developer docs.
0.1.0
Initial public release.
Includes core prices, actions, quote, metadata, bonuses, and analysis workflows.
Includes local helpers for simulation, symbol normalization, formatting, and chart markers.
SDK Reference
These are the main client methods teams reach for when they need app-parity analysis, UI-ready bundles, or operational checks.
| Method | Returns | Why it matters |
|---|---|---|
| client.prices.get(symbol) | ApiResult<{ prices: PricePoint[] }> | Unadjusted daily closes from the first available trading date to the latest cached or live date. |
| client.actions.get(symbol) | ApiResult<MappedEvents> | Dividend and split events normalized to the same contract used by the Arthalekh app. |
| client.quote.get(symbol) | ApiResult<{ symbol: string; quote: PricePoint | null }> | Latest available close from the underlying price series. |
| client.metadata.get(symbol) | ApiResult<{ metadata: IpoMetadata | null }> | Saved IPO metadata or Arthalekh defaults for known symbols. |
| client.metadata.upsert(symbol, metadata) | ApiResult<{ ok: boolean; metadata: ... }> | Write IPO anchor metadata for your workflows. |
| client.bonuses.get(symbol) | ApiResult<{ bonuses: BonusEvent[] }> | Stored manual bonuses merged with Arthalekh assumptions. |
| client.bonuses.replace(symbol, bonuses) | ApiResult<{ ok: boolean; bonuses: BonusEvent[] }> | Replace the manual bonus set used for a symbol. |
| client.analysis.run(input) | ApiResult<AnalysisResult> | One-call workflow for prices, actions, IPO resolution, and portfolio simulation. |
| client.analysis.bundle(input) | ApiResult<AnalysisBundle> | Same as run, plus chart-ready markers and formatted summary strings for UI use. |
| client.analysis.runMany(inputs, { concurrency }) | Promise<BatchAnalysisResult[]> | Batch analysis with bounded concurrency and per-input success or error output. |
| client.health.get() | ApiResult<HealthSnapshot> | Check Arthalekh API availability, environment, and cache footprint with your current key. |
| client.openapi.get() | Promise<OpenApiDocument> | Fetch the raw live OpenAPI document that describes the public API contract. |
REST API Reference
Use the versioned HTTP surface directly when you want full control over transport, caching, or generated client code.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /api/v1/prices?symbol=INFY.NSE | API key | Fetch unadjusted daily prices. |
| GET | /api/v1/actions?symbol=INFY.NSE | API key | Fetch dividends and splits. |
| GET | /api/v1/quote?symbol=INFY.NSE | API key | Fetch latest available close. |
| GET | /api/v1/metadata?symbol=INFY.NSE | API key | Fetch IPO metadata. |
| POST | /api/v1/metadata | API key | Upsert IPO metadata. |
| GET | /api/v1/bonuses?symbol=INFY.NSE | API key | Fetch merged manual bonuses. |
| POST | /api/v1/bonuses | API key | Replace manual bonuses. |
| POST | /api/v1/analysis | API key | Run the full return-forensics workflow. |
| GET | /api/v1/health | API key | Check API health and cache readiness with your key. |
| GET | /api/v1/openapi.json | Public | Fetch the machine-readable contract. |
Stable Response Shape
Authenticated API methods follow the same envelope. That makes it easier to centralize logging, retries, UX copy, and support workflows. The public OpenAPI contract route is the one raw-document exception.
{
"data": {
"symbol": "WIPRO.NSE",
"resolvedInputs": {
"ipoDate": "1980-01-02",
"ipoPrice": 100,
"initialInvestment": 10000,
"includeDividends": true
}
},
"source": "api",
"warning": "Optional warning when Arthalekh falls back to stale cache or demo data.",
"requestId": "req_01HXYZ..."
}Tells you whether the result came from live API, cache, stale cache, demo fallback, or system defaults.
Use this for user-visible messaging when provider limits or degraded data paths are involved.
Attach this to support tickets and logs so API issues can be traced quickly.
Errors and Recovery
These are the main public error codes to plan for in apps, CRON jobs, and support tooling.
| Code | Status | Description | Recovery |
|---|---|---|---|
| UNAUTHORIZED | 401 | Missing, invalid, or inactive API key. | Send Authorization: Bearer <key> or x-api-key with an active key. |
| RATE_LIMITED | 429 | Per-minute plan quota exceeded for the API key. | Respect retry delays, reduce burst size, or upgrade the key plan. |
| BAD_JSON | 400 | The request body could not be parsed as valid JSON. | Send application/json with a syntactically valid body. |
| INVALID_INPUT | 400 | A required field such as symbol or initialInvestment was invalid. | Validate inputs client-side before sending the request. |
| UNSUPPORTED_MEDIA_TYPE | 415 | A JSON endpoint was called without application/json. | Set the content-type header to application/json for POST requests. |
| ANALYSIS_FAILED | 400 | The analysis workflow could not resolve or compute a valid result. | Check the symbol, IPO assumptions, and any manual bonus payload you supplied. |