Skip to content

Quickstart (Bulk Files)

Pull the whole standardized-fundamentals corpus as nightly compressed files — instead of thousands of per-company calls — and load it straight into your warehouse.

1. Get your API key

Bulk downloads use the same API key as every other endpoint. Create one on the Credentials page.

2. Read the manifest first

The manifest is the entry point for any bulk workflow. It lists the files in the most recent nightly snapshot — each with a row count, byte size, and SHA-256 digest — plus the snapshot timestamp. Two datasets ship today: standardized_values (every company’s currently-in-force standardized line items) and entities (the company identity dimension, so you can join without a second call).

manifest · cURL · bash
curl "https://api.finradar.ai/api/v1/xbrl/bulk" \
  -H "X-API-Key: YOUR_API_KEY"

3. Download a file

Each file is gzip newline-delimited JSON (one JSON object per line), streamed from disk. Large downloads are resumable (HTTP Range requests are supported).

download · cURL · bash
# Download one file from the latest snapshot (streamed, resumable).
curl "https://api.finradar.ai/api/v1/xbrl/bulk/standardized_values.ndjson.gz" \
  -H "X-API-Key: YOUR_API_KEY" \
  -o standardized_values.ndjson.gz

# Read it: gunzip, then one JSON object per line.
gunzip -c standardized_values.ndjson.gz | head -n 1

4. A complete nightly ingest

Read the manifest, compare the snapshot to the last one you ingested, download only when it changed, then read the rows:

nightly ingest · Python · python
import gzip, json, requests

BASE = "https://api.finradar.ai"
HEADERS = {"X-API-Key": "YOUR_API_KEY"}

# 1. Read the manifest — the entry point for any bulk workflow.
manifest = requests.get(f"{BASE}/api/v1/xbrl/bulk", headers=HEADERS).json()["data"]
print("snapshot:", manifest["snapshot"], "rows:", manifest["total_rows"])

# 2. Download only when the snapshot changed since your last ingest.
target = next(f for f in manifest["files"] if f["dataset"] == "standardized_values")
r = requests.get(f"{BASE}{target['download_path']}", headers=HEADERS, stream=True)
with open(target["filename"], "wb") as fh:
    for chunk in r.iter_content(chunk_size=1 << 20):
        fh.write(chunk)

# 3. Read the rows — gzip newline-delimited JSON, one object per line.
with gzip.open(target["filename"], "rt") as fh:
    for line in fh:
        row = json.loads(line)
        # row -> {cik, ticker, metric, fiscal_year, fiscal_period, value, unit, ...}
        break

Verify before you ingest

Each file entry carries a sha256 digest. Check your downloaded bytes against it before loading, so a truncated download never silently corrupts your data.