graph datapoint builds a complete ownership tree by recursively fetching shareholders across multiple countries and traversal depths. Starting from a root company, Topograph follows corporate shareholder chains (resolving each company in its local registry) to produce a full graph of entities and ownership relationships.
The result includes UBO (Ultimate Beneficial Owner) calculations based on accumulated ownership and control established from ownership percentages.
graph is a verification-only datapoint. The traversal resolves each node against its live local register, so it cannot complete within the prefill deadline. Requesting graph with mode: "prefill" fails immediately with fast_source_unavailable, without fetching or billing anything. See Modes.graph is not available in development environments: requests for it there fail with datapoint_not_supported.Example Request
How It Works
- Root fetch: Retrieves the company profile and shareholders from the root company’s registry
- Shareholder resolution: For each corporate shareholder, searches the relevant country’s registry to find the company
- Recursive traversal: Fetches shareholders for each resolved company, building the tree level by level
- UBO calculation: Identifies individuals through accumulated ownership or ownership-based control
Traversal Limits
The graph traversal has built-in limits to control scope and cost:
When any limit is reached, the graph returns all data collected up to that point with a
stoppedReason indicating why traversal stopped.
Need higher limits? If your use case requires deeper traversals or more entities, contact us to discuss your requirements.
Stopped Reasons
Themetadata.stoppedReason field indicates how the traversal ended:
Response Structure
The graph result is included alongside the standard company data:Node Flags
A node with
status: "budget_truncated" is a placeholder for a corporate shareholder the traversal did not fetch (because of graphMaxBudget, graphInteractive, or a depth/entity limit). It carries the nodeId and a cost preview, and can be passed to graphContinueFromNodeIds in a follow-up request to resume from there.
A node with status: "coverage_unavailable" is a corporate shareholder in a country where shareholder data is not available. The branch ends there, and the node cannot be passed to graphContinueFromNodeIds.
UBO calculation
The graph evaluates each individual independently using two methods.totalOwnershipPercentage always reports economic ownership, calculated by multiplying percentages along each ownership chain and adding the results across chains.
Accumulated ownership
accumulation qualifies an individual with at least 25% direct or indirect ownership. For example, 60% of a holding company that owns 30% of the target contributes 18%. Another 10% held directly brings the total to 28%.
Ownership-based control
domination qualifies an individual through a majority-control chain or a mixed ownership and control structure:
- More than 50% establishes control of a company. Control can continue through successive majority-controlled companies, including stakes held cumulatively through controlled companies.
- An individual controlling companies that together hold at least 25% directly in the target qualifies through control.
- An individual with at least 25% accumulated ownership in a company controlling the target also qualifies.
A control-qualified individual can therefore have
isUbo: true while totalOwnershipPercentage is below 25%. Exactly 50% does not establish majority control by itself.
These calculations implement the ownership-based rules in Articles 51–54 of Regulation (EU) 2024/1624. The regulation generally applies from 10 July 2027. The calculation does not determine which legal standard applies to your case.
The graph does not assess separate voting rights, board appointment powers, vetoes or contractual control. Missing percentages and unresolved branches cannot establish control. Review source coverage and traversal limits before treating a graph as complete.
graph datapoint. They do not replace beneficial owners reported by a register through the ultimateBeneficialOwners datapoint. Existing stored graph results retain their previous calculations; newly calculated graphs and merged continuations use the current rules.
Interactive mode
SetgraphInteractive: true to fetch only the entry company and return its direct shareholders. Companies among those shareholders come back as budget_truncated placeholders so the caller decides which branches to expand. Each chip click is one fetch and one billing event.
graphInteractive and graphMaxBudget are mutually exclusive. When graphInteractive is true, the budget value is ignored.
The response carries graph.metadata.interactive: true so a stored result is self-describing, and graph.metadata.stoppedReason reads max_depth_reached.
Continuing from a previous request
To extend a graph from one or morebudget_truncated placeholders, pass their nodeIds in graphContinueFromNodeIds and link to the parent through mainRequestId. countryCode and id are derived from the parent automatically.
graphInteractive: true, every continuation inherits the flag. The seeded node is fetched and its own direct shareholders are surfaced as a fresh layer of placeholders, ready for the next click.
Best Practices
Pick the right control: budget vs. interactive
Pick the right control: budget vs. interactive
Use
graphMaxBudget when you want a single response with as much of the tree as fits within a known cost ceiling. Use graphInteractive when you want predictable per-step cost and a deterministic UI: one fetch per request, the rest of the tree visible only as continuation handles you choose to expand.Set an appropriate budget
Set an appropriate budget
The
graphMaxBudget parameter is the primary way to control non-interactive traversal scope. Without it, a non-interactive traversal has no credit ceiling, so always set it (or use graphInteractive) to cap spend. Start with a lower budget for exploration, then increase if you need deeper coverage. Each company lookup costs the standard price for that country.Expect variable execution times
Expect variable execution times
Graph traversal time depends on the number of companies, the countries involved, and registry response times. Simple structures (1-2 levels, single country) complete in seconds. Complex multi-country structures with deep chains can take several minutes. Interactive requests are bounded by a single company fetch, so they return as fast as that country’s registry replies.
Handle partial results
Handle partial results
When a limit is reached, the graph returns everything collected so far. Check
metadata.stoppedReason to understand why traversal stopped and whether requesting again with a higher budget, or extending via graphContinueFromNodeIds, would yield more data.