API schema reference

Field-by-field reference for the two datasets exposed via the API. See /developers for endpoints and authentication, and /methodology for per-country coverage and known caveats.

filings — managers' transactions (PDMR / MAR Article 19)

One row per regulator-published transaction. The deterministic id means re-scraping is idempotent: the same source filing always lands on the same row.

FieldTypeNull?Description
idtext (PK)noDeterministic id: scraper-prefix + regulator-reference + insider id + transaction date + price + value. Stable across re-scrapes.
countrytext (ISO 3166-1 alpha-2)noRegulator's jurisdiction. Note Norwegian filings reach us via Euronext, so country='NO' but listing exchange may differ.
insider_idtextnoStable id of the manager: normalize(name) + '__' + normalize(company). See lib/types.ts:makeInsiderId.
insider_nametextnoAs published by the regulator. Diacritics preserved.
insider_roletextyesPosition / status string from the regulator (e.g. 'Vorstand', 'CEO', 'Director'). Not normalized — language follows source.
company_nametextnoIssuer name as published. Sometimes differs slightly from listing name (e.g. 'SAP SE' vs 'SAP').
isintextyes12-char ISIN. Always present where the source provides it; missing on a few signal-only sources.
tickertextyesYahoo-Finance-compatible ticker (e.g. 'SAP.DE'). Populated asynchronously by ISIN→ticker enrichment, may be null for up to 24h after ingestion.
exchangetextyesListing exchange string from the source (e.g. 'XETRA', 'SIX', 'Tradegate'). Free-form — no canonical taxonomy.
transaction_datedatenoDate the trade was executed (regulator-reported). YYYY-MM-DD.
filing_datedatenoDate the regulator received / published the filing. Always ≥ transaction_date.
transaction_typeenum: 'buy' | 'sell'noNormalized buy/sell. Regulator-specific labels (Kauf/Verkauf, achat/vente, acquisition/disposal) are mapped via per-source rules. Non-equity events (subscription, option exercise) are skipped at scrape time.
sharesbigintyesNumber of shares. Where the regulator reports value+price but not shares, we derive as round(value/price). NULL on signal-only sources.
pricenumericyesAverage price per share in the local trading currency. NULL on signal-only sources.
value_eurnumericyesAggregate transaction value in EUR. Native-currency values are converted using the ECB reference rate at transaction_date. NULL on signal-only sources.
currencytext (ISO 4217)noOriginal currency of the transaction. EUR for euro-area. Defaulted to 'EUR' when the source doesn't disambiguate.
source_urltextyesURL pointing back to the regulator filing or detail page. Used for provenance.
raw_datajsonbyesOriginal regulator payload for the row, unmodified.

substantial_holdings — Transparency Directive crossings

One row per regulator-published threshold crossing (5% / 10% / 25% / 50% / 75% of voting rights, per the EU Transparency Directive).

FieldTypeNull?Description
idtext (PK)noDeterministic id: scraper-prefix + regulator-reference + filer + issuer + filing date.
countrytext (ISO 3166-1 alpha-2)noRegulator's jurisdiction.
filer_nametextnoEntity that crossed the threshold (fund, person, holding company). As published.
filer_idtextyesWhere regulator provides a stable id (LEI, BaFin id, etc.) — populated. Otherwise NULL.
issuer_nametextnoIssuer whose shares the filer holds.
issuer_isintextyesISIN of the issuer's primary listing. Populated where the regulator provides it; many sources return NULL.
issuer_tickertextyesYahoo-Finance-compatible ticker. Populated asynchronously after ingestion.
filing_datedatenoDate the regulator published the threshold-crossing filing.
event_datedateyesDate the threshold was actually crossed (always ≤ filing_date). May be missing in signal-only sources.
threshold_pctnumericyesThe threshold that was crossed (typically 5, 10, 15, 20, 25, 30, 50, 75).
directiontextyes'up' (acquisition crossed up) or 'down' (disposal crossed down).
new_pctnumericyesPost-trade ownership percentage. Currently sparse — most non-DE sources return NULL.
previous_pctnumericyesPre-trade ownership percentage. Sparse.
voting_rights_countbigintyesTotal voting rights held after the event. Sparse.
regulationtextyesSpecific transparency regulation invoked (e.g. '§135 BörseG' for AT, 'WpHG §33' for DE, 'TR-FER 5.1' for GB).
source_urltextyesURL to the original regulator filing.
raw_datajsonbyesOriginal regulator payload, unmodified.

Notes on nullability

  • For signal-only scrapers (most regulators outside DE / SE / CH — see /methodology), shares, price, and value_eur are NULLon filings rows because the values live inside source PDFs we don't parse in v1.
  • ticker is populated by an asynchronous ISIN-to-ticker enrichment job and may be NULL on freshly-ingested rows for up to 24 hours.
  • raw_datacontains the full original regulator payload for that row, structured exactly as the source returned it. Useful for any field we don't surface in our typed schema.