API documentation
Everything is served under /v1, returns JSON (or CSV on request), and requires an API key. The interactive endpoint reference lives at https://api.arclanetechnologies.com/v1/docs.
1 · Get a key
Create an account, verify your email, and generate a key. It's shown once — store it like a password. Free keys get the latest two published years of every company (showcase companies: full history). Paid keys get everything.
2 · Authenticate
Send the key on every request:
Authorization: Bearer atlas_sk_your_key_here
3 · First request — coverage
curl "https://api.arclanetechnologies.com/v1/companies" \ -H "Authorization: Bearer atlas_sk_..."
Returns every published company with its years, statements and years_on_plan — the years your key can access.
4 · A statement, with lineage
curl "https://api.arclanetechnologies.com/v1/companies/JKH/financials?year=FY2025&statement=income_statement&include=components" \ -H "Authorization: Bearer atlas_sk_..."
include=components attaches the composition lineage to every field: the printed label, note reference, row index, sign-normalisation flag, and the source report + page each figure came from. Add &format=csv (or send Accept: text/csv) for CSV.
5 · Python
import requests
API = "https://api.arclanetechnologies.com/v1"
KEY = "atlas_sk_..."
r = requests.get(
f"{API}/companies/JKH/financials",
params={"year": "FY2025", "statement": "income_statement"},
headers={"Authorization": f"Bearer {KEY}"},
)
r.raise_for_status()
data = r.json()
for f in data["statements"]["income_statement"]["fields"]:
print(f["field"], f["consolidated_current"])6 · Five years of revenue into pandas
The timeseries endpoint is the core institutional use case: one field, every published year, one request.
import pandas as pd
import requests
API = "https://api.arclanetechnologies.com/v1"
KEY = "atlas_sk_..."
r = requests.get(
f"{API}/companies/JKH/timeseries",
params={"field": "revenue", "entity": "consolidated", "units": "lkr"},
headers={"Authorization": f"Bearer {KEY}"},
)
r.raise_for_status()
df = pd.DataFrame(r.json()["series"])
df["year"] = df["year"].str.replace("FY", "").astype(int)
df = df.set_index("year")
print(df)
# value unit
# year
# 2021 ... rupees
# 2022 ... rupeesunits=lkr converts everything to absolute rupees — report units can differ across years, and this saves you checking. Leave it off to get values exactly as reported, with a unit per point.
Errors & rate limits
Errors always have one shape: {"error": {"code": "...", "message": "..."}}. Codes you'll see: unauthorized (401, bad or missing key), plan_required (403, the year is outside your plan), not_found (404, no published data), rate_limited (429).
Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; a 429 includes Retry-After in seconds. Free: 20 requests/min, 1,000/day. Paid: 120/min, 20,000/day.
Field definitions
GET https://api.arclanetechnologies.com/v1/meta/schema?sector=general returns every normalized field per statement with its flags — subtotal (printed subtotal, recomputed and cross-checked by our validation), bucket (heterogeneous rows may map into it), memo (per-share/off-balance items excluded from sums). No key required.