Skip to main content

Supply-chain graph

Typed single-hop edges that let you reconstruct who a company ships to, who owns it, and who litigates against it — without stitching together six separate connectors.

Three sub-graphs cooperate:

Sub-graphFiling primitiveWhat it returns
Entity.parentSchedule 13D/GControlling shareholder (>50%) with reported ownership percentage
Entity.subsidiariesExhibit 21 (10-K / 20-F)Consolidated legal subsidiaries with jurisdictions
Entity.concentrationXBRL segment filingsHHI + top shares per product / segment / geography / customer
Entity.relationshipsAll of the above + 13F + alt-dataFlat list of typed edges (CUSTOMER, SUBSIDIARY, GOVERNMENT_CUSTOMER, PARTNER, ADVERSARIAL, OWNERSHIP)

relationships is the unified view — if you only want one call per entity, use that. subsidiaries and concentration give you the structured primitives backing it.

Parent company

Entity.parent returns the controlling shareholder when one exists — the filer of the most recent Schedule 13D/G where percentOwned exceeds 50%. Null when no shareholder crosses the majority threshold.

{
entitiesByTickers(tickers: ["LCID", "IMVT", "AAPL", "GOOGL"]) {
tickers
parent {
name
cik
percentOwned
source { connector url asOf ref }
}
}
}

Expected: LCID → Ayar Third Investment Co (~64%, Saudi PIF vehicle); IMVT → Roivant Sciences Ltd. (~55%); AAPL and GOOGLnull (no single 13D/G filer crosses 50%).

Percent is parsed from Item 13 (SC 13D) / Item 9 (SC 13G): "Percent of class represented by amount in row (11)". "Less than 1%" is normalized to 0.5.

What the field captures

Post-IPO secondary 13D filings (spin-offs, leveraged buyouts, private takeovers, sovereign-wealth stakes). Ownership is reported per-filer — when a filer's most recent filing reports < 50%, they're excluded even if an older filing was above the threshold (a divestiture wiping out prior control).

What it won't catch

Majority ownership disclosed via S-1 / 10-K registration (e.g. Intel's ~88% of MBLY, SoftBank's ~90% of ARM) — those parents don't file Schedule 13D because ownership is already on the registration statement. For that case, pair this field with Entity.subsidiaries on the parent company, or use Entity.relationships(filter: { types: [OWNERSHIP] }).

Super-voting founder control (Zuckerberg at META, Page/Brin at GOOGL) is reported as the economic percentage, not the voting percentage — so those filings correctly fall below the 50% gate.

Consolidated subsidiaries

Entity.subsidiaries returns the subsidiary table parsed from the most recent 10-K or 20-F Exhibit 21.

{
entityByTicker(ticker: "AAPL") {
subsidiaries {
accessionNumber
form
filingDate
exhibitUrl
count
subsidiaries { name jurisdiction }
}
}
}

Returns null when the entity has no recent 10-K / 20-F on file (foreign private issuers, non-public entities).

Revenue concentration (HHI)

Entity.concentration computes Herfindahl-Hirschman Index scores from XBRL segment disclosures. Each dimension (product / segment / geography / customer) returns hhi, count, total, and components ordered largest-first.

{
entityByTicker(ticker: "AAPL") {
concentration {
form periodEnd
product { hhi count total components { label value share } }
geography { hhi count total components { label value share } }
segment { hhi count total components { label value share } }
customer { hhi count total components { label value share } }
}
}
}

customer is null unless the issuer disclosed major-customer concentration under ASC 280 (MajorCustomersAxis). Dimensions the issuer doesn't disclose are also null — they are never fabricated from adjacent data.

Relationship edges

Entity.relationships(filter: RelationshipFilterInput) is the single call that rolls everything up. Each edge carries:

  • type — one of CUSTOMER, SUBSIDIARY, GOVERNMENT_CUSTOMER, PARTNER, ADVERSARIAL, OWNERSHIP
  • directionOUT (the subject → counterparty) or IN (counterparty → subject)
  • disclosureSELF_REPORTED (company's own filing) vs THIRD_PARTY (court docket, trial registry, etc.)
  • confidence — 0.0 – 1.0 (anonymized customer labels like "Customer A" emit at 0.4)
  • counterpartyName, counterpartyTicker, counterpartyCik — what you hop to next
  • sharePct, valueUsd, context — edge metadata when available
  • source{ connector, url, asOf, ref } provenance
{
entityByTicker(ticker: "AAPL") {
relationships(filter: {
types: [SUBSIDIARY, CUSTOMER, OWNERSHIP, PARTNER, GOVERNMENT_CUSTOMER]
minConfidence: 0.5
limit: 20
sort: DESC
}) {
type direction confidence
counterpartyName counterpartyTicker counterpartyCik
sharePct valueUsd context
source { connector asOf ref url }
}
}
}

Filter reference

input RelationshipFilterInput {
types: [RelationshipType!] # CUSTOMER | SUBSIDIARY | GOVERNMENT_CUSTOMER | PARTNER | ADVERSARIAL | OWNERSHIP
directions: [RelationshipDirection!] # OUT | IN
minConfidence: Float # 0.0 – 1.0
minValue: Float # USD floor on valueUsd
since: String # ISO 8601 on source.asOf
until: String # ISO 8601 on source.asOf
limit: Int # default 50, cap 500
offset: Int
sort: SortDirection # DESC default (newest asOf first)
}

Two-hop traversal (supply-chain walks)

A client can reconstruct "Apple → chips supplier → supplier's geography" with two batched calls. Hop 0 pulls Apple's outgoing edges; hop 1 batches the counterparty tickers back through entitiesByTickers to pull their concentration.geography and incoming CUSTOMER edges.

{
entityByTicker(ticker: "AAPL") {
relationships(filter: {
types: [CUSTOMER, SUBSIDIARY, OWNERSHIP, PARTNER]
directions: [OUT]
minConfidence: 0.5
limit: 50
}) {
type counterpartyTicker counterpartyName sharePct context
source { connector asOf }
}
}
}

Combining with alt-data

Because relationships is aggregated from the existing connectors, pulling it alongside litigation or governmentContracts is deduplicated at the request-scoped cache level — you pay for one upstream hit, not two.

{
entitiesByTickers(tickers: ["LMT", "RTX"]) {
relationships(filter: { types: [GOVERNMENT_CUSTOMER], minValue: 1000000, limit: 5 }) {
counterpartyName valueUsd context source { asOf ref }
}
governmentContracts(filter: { minAmount: 1000000, limit: 5 }) {
awardId amount agency awardType actionDate
}
}
}

See Sub-graphs for batching semantics and Filtering & sorting for generic ArrayFilterInput usage.