Kappa Data APIDocumentation
Public docs · API beta

TradePolaris Data API

Discover versioned datasets, inspect their schema, query bounded rows, and export an immutable Parquet version through one read-only API.

The reference is public. Calling the API requires an approved Kappa account and an active key.

Base URL
https://api.tradepolaris.com/platform/v1
Authentication
Bearer API key
Access model
Read-only datasets
Response formats
JSON, CSV, Parquet
Start here

Make your first request

Search for a dataset first, inspect its schema, and only then choose filters. This avoids guessing slugs, columns, date fields, or point-in-time support.

  1. 1
    Create a key

    Approved accounts create keys in the authenticated Data API console. Store the show-once secret in a secrets manager.

  2. 2
    Search, then inspect

    Resolve a dataset with GET /datasets?q=…, then read /schema before querying rows.

  3. 3
    Query or export

    Use bounded JSON for applications, complete-or-rejected CSV for filtered extracts, or checksummed Parquet for a full immutable version.

curlcopy-ready
export TP_API_KEY="tp_live_..."

curl --fail-with-body \
  --header "Authorization: Bearer $TP_API_KEY" \
  "https://api.tradepolaris.com/platform/v1/datasets?q=apple&limit=10"
Python · requestscopy-ready
import hashlib
import os
import requests

BASE_URL = "https://api.tradepolaris.com/platform/v1"
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['TP_API_KEY']}"

# Search first; do not page the full catalog.
catalog = session.get(
    f"{BASE_URL}/datasets",
    params={"q": "apple", "limit": 10},
)
catalog.raise_for_status()
dataset = catalog.json()[0]["name"]

# Inspect capabilities before choosing filters.
schema_response = session.get(f"{BASE_URL}/datasets/{dataset}/schema")
schema_response.raise_for_status()
schema = schema_response.json()

# JSON rows are paginated and DataFrame-ready.
rows_response = session.get(
    f"{BASE_URL}/datasets/{dataset}/query",
    params={"start": "2026-01-01", "limit": 5000},
)
rows_response.raise_for_status()
page = rows_response.json()
print(page["columns"], page["rows"], page["truncated"])

# For the immutable full version, verify the exported Parquet bytes.
export_response = session.get(f"{BASE_URL}/datasets/{dataset}/export")
export_response.raise_for_status()
artifact = export_response.json()
download = requests.get(artifact["url"])  # no API Authorization header
download.raise_for_status()
expected_sha256 = artifact.get("content_sha256")
if not expected_sha256:
    raise RuntimeError("Export did not include a checksum")
assert hashlib.sha256(download.content).hexdigest() == expected_sha256
Access

Authentication and scopes

Send the key on every request. The secret begins with tp_live_, is shown once, and cannot be retrieved later.

HTTP headercopy-ready
Authorization: Bearer tp_live_...
Recommended

Curated scope

Reads the shared catalog and curated market datasets. The account's own uploads stay absent from search and return 404 on direct reads.

Internal only

All-datasets scope

Adds datasets owned by the same account. Use it only for trusted internal services that genuinely need those rows.

  • Keys expire after 1–365 days; the default is 90 days.
  • Up to five keys can be active on one account.
  • Optional IPv4 and IPv6 CIDRs restrict where a key may be used. An empty list means unrestricted.
  • Rotation preserves the service-account identity and can keep the predecessor valid for a bounded handover.
  • Revocation rejects the key immediately on every API endpoint.
Reference

Dataset endpoints

Every path below is relative to https://api.tradepolaris.com/platform/v1. The integration surface is structured and read-only; callers cannot submit SQL or arbitrary ordering.

GET/datasets

Find a dataset

Search the datasets visible to the key. The catalog is large and alphabetically paged, so search by name or label instead of walking every page.

Parameters for GET /datasets
ParameterTypeMeaning
qstringSearch dataset names and human labels. For example, q=apple matches us-eq-aapl-1d.
asset_classenumOptional family filter: equity, intl, futures, fx, crypto, fundamentals, options, news, positioning, or macro.
limitinteger · 1–500default 200Maximum catalog rows in this page.
offsetinteger · ≥0default 0Zero-based catalog offset.

Response

body
An array of dataset summaries: name, kind, latest_version, source, license, description, owned, updated_at, and asset.
X-Has-More
The reliable pagination signal. Do not infer completion from the returned row count.
GET/datasets/{name}/preview

Preview its shape

Return a render-ready sample as line points, candles, or table rows. Use schema or query when a dataset is too large to preview.

Parameters for GET /datasets/{name}/preview
ParameterTypeMeaning
namerequiredstringDataset slug returned by GET /datasets.
versioninteger · ≥1Pinned dataset version. Omit to use the latest version.
max_pointsintegerdefault 500Requested preview density. Values are safely clamped to 10–2,000 points.

Response

chart
line, candles, or table; identifies the populated payload field.
points / candles / rows
The render-ready preview payload.
total_rows / downsampled
Full version size and whether the preview was thinned.
GET/datasets/{name}/schema

Inspect the schema

Read columns, dtypes, coverage, detected time and symbol fields, and the producer-declared capability contract before querying rows.

Parameters for GET /datasets/{name}/schema
ParameterTypeMeaning
namerequiredstringDataset slug returned by GET /datasets.
versioninteger · ≥1Pinned dataset version. Omit to use the latest version.

Response

columns[] / row_count
Column names and dtypes plus the version's total row count.
date_column / symbol_column
Detected effective-time and symbol fields when present.
date_min / date_max
Dataset- and version-specific coverage bounds.
capabilities
The source contract, including point_in_time_supported, time fields, revision_model, valid query operators, and provenance.
GET/datasets/{name}/query

Query rows

Apply structured filters and column projection. This is not a SQL endpoint. JSON is paginated; CSV is complete-or-rejected up to 1,000,000 matching rows.

Parameters for GET /datasets/{name}/query
ParameterTypeMeaning
namerequiredstringDataset slug returned by GET /datasets.
versioninteger · ≥1Pinned dataset version. Omit to use the latest version.
symbolstring · ≤32 charsExact symbol filter when the schema declares a symbol column.
startISO dateInclusive lower bound on the dataset's effective date field.
endISO dateInclusive upper bound on the dataset's effective date field.
as_ofYYYY-MM-DDPoint-in-time knowledge bound. Use only when schema.capabilities.point_in_time_supported is true; unsupported datasets return 400.
columnscomma-separated stringProjected column names.
limitinteger · 1–5,000default 500Maximum rows in a JSON page.
offsetinteger · ≥0default 0JSON page offset.
tailbooleandefault falseFor JSON, keep the newest bounded window instead of the oldest one. CSV is already the complete filtered result.
formatjson | csvdefault jsonJSON returns a bounded page. CSV returns the complete filtered result or rejects it before sending partial bytes.

Response

columns / rows
Column names and row arrays, ready to construct a DataFrame.
total_matched / returned / truncated
Exact match count and page status for JSON responses.
as_of evidence
When applied: as_of, knowledge_time_column, knowledge_time_min, and knowledge_time_max.
CSV headers
X-Total-Rows is the emitted row count and X-Export-Complete: true confirms the body was not clipped.
GET/datasets/{name}/export

Export a pinned version

Mint a short-lived URL for the immutable Parquet artifact. Download the URL without an Authorization header and verify its SHA-256 checksum.

Parameters for GET /datasets/{name}/export
ParameterTypeMeaning
namerequiredstringDataset slug returned by GET /datasets.
versioninteger · ≥1Pinned dataset version. Omit to use the latest version.
as_ofunsupportedDo not send this parameter. The endpoint returns 400 rather than silently exporting unfiltered history; use /query with as_of.

Response

url / expires_in
A bearer download URL and its lifetime in seconds: 900 for curated datasets and 300 for account-owned uploads.
name / version / bytes / rows
Immutable artifact identity and size.
content_sha256
Checksum to verify after download.
Completeness

Pagination without silent truncation

Catalog

Increase offset while the response header X-Has-More is true. A short page can still have more results.

JSON rows

Increase offset while truncated is true. total_matched is the exact filtered count.

Newest window

Set tail=true to keep the newest bounded window. It does not enable arbitrary sorting.

CSV

A successful CSV is complete and carries X-Export-Complete: true. Oversized results fail before any partial body is sent.

Historical truth

Point-in-time queries are capability-based

Use as_of=YYYY-MM-DD only when the resolved schema says capabilities.point_in_time_supported: true. The bound means “known by the end of that UTC date” on the declared availability field. Unsupported datasets return 400 instead of silently ignoring the bound.

Do not infer support from a dataset name or column.

Read time_field, availability_time_field, revision_model, and the response's knowledge_time_min / knowledge_time_max. An empty result before the retained floor is not evidence that no filing or disclosure existed.

Dataset families with point-in-time support
Catalog selectorAvailabilityEffective timeRevision model
us-13f-hist-*filing_dateperiodfiling_history_with_amendments
us-form4-*filing_datetransaction_datefiling_history_with_amendments
house-ptr-*filed_datetransaction_daterolling_disclosure_history

Coverage is dataset- and version-specific. Inspect date_min and date_max; Kappa makes no catalog-wide history promise. See the complete machine-readable capability matrix.

SEC 13F integration notes

History lanes retain accessions, including amendments; they are not amendment-resolved canonical portfolios. ADD-type amendments and firms that file through multiple entities require consumer-side interpretation. Do not infer a complete manager position unless an amendment-resolved portfolio is supplied.

Put, call, and unflagged positions remain distinct history rows. Use value_usd for normalized values; value preserves the raw SEC number and its unit changes across filing eras.

pct_of_filing_value is a weight within one accession. The legacy pct_of_portfolio field is a deprecated alias, not a canonical firm-level portfolio weight.

US equity reference data includes active and inactive/delisted symbols where supplied. That reduces survivorship bias but does not certify every dataset or historical universe as survivorship-free.

Bulk data

Handle exports as short-lived bearer artifacts

  • Download the returned URL with a plain GET. Do not attach the TradePolaris API key to the object-storage request.
  • Verify content_sha256 before accepting the file. Versions are immutable, so a pinned re-download should be byte-identical.
  • Do not log, share, or persist the URL. Anyone holding it can download until it expires.
  • Revoking the API key does not invalidate URLs already issued; their TTL is the remaining exposure window.
  • The URL-bearing response is Cache-Control: no-store.
  • The export endpoint does not support as_of. Use a point-in-time CSV query when the filtered result fits the documented row ceiling.
Operations

Errors and retries

The default normal-capacity budget is 120 requests per minute per key and can vary by plan. On 429, wait for Retry-After. Retry transient 503 responses with capped exponential backoff.

400
The request asks for unsupported semantics, such as as_of on a dataset that does not declare point-in-time support.
401
The bearer key is missing, malformed, expired, revoked, or unknown.
402 dataset_limit
The monthly distinct-dataset export meter is exhausted.
403
The account is not entitled to Data API access, or the key's source-CIDR policy denies the trusted client address.
404
The dataset does not exist or is outside this key's scope. Private datasets are concealed rather than disclosed with 403.
413
The preview is too large, or a CSV query matches more than 1,000,000 rows. Narrow the query or use Parquet export.
422
One or more parameters failed validation.
429
The per-key request budget is spent. Wait for Retry-After, then retry.
503
A transient fail-closed service guard rejected the request. Retry with backoff.
Account API

Key-management routes use account authentication

A Data API key cannot create, list, rotate, edit, or revoke other keys. These routes require an authenticated TradePolaris account session or account JWT. Ownership comes from that identity and cannot be supplied in the request body.

POST /api-keys
Create a key and return its secret once.
GET /api-keys
List credential history and metadata; never returns secrets.
POST /api-keys/{id}/rotate
Create a same-principal successor with a bounded overlap.
PATCH /api-keys/{id}
Update the label or source-CIDR policy.
DELETE /api-keys/{id}
Revoke immediately while retaining credential history.
Agents & SDKs

One contract for people and machines

The page is server-rendered with semantic headings, tables, code, and stable fragment IDs. Parsers can use the same reference in two machine-oriented formats:

The root llms.txt file links these artifacts so an agent discovering TradePolaris from the site index can reach the integration contract directly.