API guide v1
One base URL, one header, tidy responses. Every endpoint returns the same envelope and honours your key's tier automatically. The machine-readable spec is openapi.yaml.
Basics
| Base URL | https://data.likefolio.com/v1 |
|---|---|
| Auth | Authorization: Bearer lf_live_… (or X-API-Key). Request a key from the trial page; it's shown once. Lost or exposed a key? Ask us for a replacement. |
| Formats | ?format=json (default) or ?format=csv (streams with a header row and no envelope). ?format=parquet and ?format=arrow return a time-limited download URL for bulk pulls. |
| Identifiers | Key by companyId (LikeFolio's canonical company id, tied to Refinitiv/LSEG permID), STABLE across ticker renames, re-listings and M&A. ticker is a mutable, point-in-time alias — resolve one to a companyId via /resolve or /universe. |
| Dates | start / end bound the event date, inclusive, YYYY-MM-DD, Eastern calendar days. kdate is a separate knowledge-date axis (see point-in-time reads). |
| Paging | Up to 50,000 rows per response. Follow next_cursor until it is null. |
| Rate limits | No throughput cap on data pulls — grab the full history as fast as you like. A burst guard stops only runaway scripts and abuse (and caps concurrent bulk jobs); 429 carries Retry-After on the rare hit. |
| Versioning | Path-versioned. v1 responses only ever gain fields. |
Envelope
{
"as_of": "2026-09-18", // date of the latest refresh behind this response
"embargo_cutoff": "2026-04-09", // trial keys: last date served (null on subscription)
"tier": "trial",
"dataset": "company_metrics",
"schema_version": "2026-09",
"rows": 1834,
"next_cursor": null,
"data": [ { "entity_id": "AAPL#consumer-electronics-dev", "company_id": "LF0000042", "perm_id": "4295905573", "ticker": "AAPL", "date": "2021-01-01", "metric": "mentions", "raw": 34297, "corrected": 34297, "flag": "" }, … ]
}
as_of is the knowledge date this response reflects (the kdate served, or the latest refresh when kdate is omitted).
Three calls to a first chart
export KEY=lf_live_xxxxxxxxxxxxxxxx
# 1. the universe (all entities, ownership windows, companyId/permID/ticker map)
curl -s -H "Authorization: Bearer $KEY" \
"https://data.likefolio.com/v1/universe?format=csv" -o universe.csv
# 2. resolve a ticker to its stable companyId (key everything else by this)
curl -s -H "Authorization: Bearer $KEY" \
"https://data.likefolio.com/v1/resolve?ticker=AAPL" # -> companyId LF0000042
# 3. one company, every metric, corrected + raw + flag
curl -s -H "Authorization: Bearer $KEY" \
"https://data.likefolio.com/v1/company/LF0000042/metrics?start=2021-01-01&format=csv" -o aapl.csv
import pandas as pd, requests
H = {"Authorization": f"Bearer {KEY}"}
u = "https://data.likefolio.com/v1/company/LF0000042/metrics" # companyId, not ticker
df = pd.DataFrame(requests.get(u, headers=H, params={"metric": "mentions,pi"}).json()["data"])
wide = df.pivot_table(index="date", columns=["entity_id", "metric"], values="corrected").sort_index()
wide.rolling(28).mean().plot()
Endpoints
| Method · path | Returns | Parameters |
|---|---|---|
GET /universe | Every entity with companyId, permID, ticker, company, ownership window, core flag (names on subscription). Carries the full companyId/permID/ticker map with dated ticker history. | company_id (comma list), ticker (comma list, point-in-time), core_only (default true), kdate |
GET /resolve | Resolve a ticker or permID (optionally as-of a kdate) to the canonical companyId to key everything else by. | ticker, perm_id, kdate |
GET /company/{companyId}/entities | The company's divisions (entities) with dated windows. Roster is point-in-time (M&A adds/retires divisions). | kdate, core_only (default false) |
GET /company/{companyId}/metrics | Company metric rows (entity × date × metric). One division with entity; company total (CORE divisions summed) with rollup=ticker. | metric (comma list, default all), entity, rollup=entity|ticker, core_only, column=corrected|raw|both, kdate, start, end |
GET /metrics/cross-section | Latest available value of one metric for every entity (screen view). | metric, date, window (trailing-day sum, default 7), kdate |
GET /trends | Trend catalog (trend_id, name, group, mapped_tickers, mapped_datasets). Names and the trend maps are included at every tier. | |
GET /trends/{trend_id}/series | Daily raw / corrected / flag for one trend. | kdate, start, end |
GET /trends/map | Trend × ticker × side with dated membership. | ticker, trend_id, as_of |
GET /company/{companyId}/search | Search interest for the company's brands (brand ids on trial). | start, end, rollup=brand|ticker |
GET /bulk | List of bulk drops (dataset, version, rows, sha256, size) with time-limited download URLs. | dataset |
GET /changelog | Every restatement and schema change, newest first. | since |
GET /status | Last refresh time per dataset, embargo cutoff, your tier and remaining quota. |
Point-in-time reads
Ownership is time-aware inside every series: at any date, an entity counts only the brands it owned that day, and a brand owned today is measured back to the epoch so year-over-year is like-for-like. You do not need to apply the windows yourself. For the trend map, pass as_of=YYYY-MM-DD to get membership as it stood.
Every metric, series and entity endpoint takes an optional kdate (knowledge date): it returns values as LikeFolio knew them on that Eastern day, with no look-ahead through later restatements (spike reclassifications, re-pulls, negations, methodology changes) or M&A. It is distinct from start/end, which bound the event date. An ISO date pins a single vintage; omit it for the latest. kdate=all returns the full bitemporal history, with kdate_from, kdate_to and change_reason on every row, for building walk-forward backtests through M&A and restatements. Because tickers are point-in-time too, keying by companyId keeps a backtest stable across a rename; resolve a ticker as-of a kdate via /resolve. Our data goes live in September 2026: there are no methodology changes or restatements before then, so kdate vintages run from go-live forward — use them to backtest through M&A and later corrections, not to claim a value was known before we built the series.
Corrections accrue forward. Every row that changes after first publication is logged with a knowledge date in /changelog; subscribers can request the append-only change file, or pull any historical vintage directly with kdate.
Errors
| Code | Meaning |
|---|---|
401 | Missing or unknown key. |
403 | Key revoked, or a subscription-only field or date range requested on a trial key. The body names the field. |
404 | companyId, entity or trend not covered, or a ticker/permID that /resolve cannot map. Coverage is dataset-specific; check /universe first. |
416 | Requested range is entirely inside the embargo window. |
429 | Rate limited; honour Retry-After. |