Skip to main content
The 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 ownership thresholds.

Example Request

curl --request POST \
  --url https://api.topograph.co/v2/company \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <api-key>' \
  --data '{
    "countryCode": "AT",
    "id": "36416d",
    "dataPoints": ["graph"],
    "graphMaxBudget": 500
  }'

How It Works

  1. Root fetch — Retrieves the company profile and shareholders from the root company’s registry
  2. Shareholder resolution — For each corporate shareholder, searches the relevant country’s registry to find the company
  3. Recursive traversal — Fetches shareholders for each resolved company, building the tree level by level
  4. UBO calculation — Identifies individuals with >25% ownership through direct or indirect chains
The traversal runs breadth-first with bounded concurrency. Each level completes before the next starts.

Traversal Limits

The graph traversal has built-in limits to control scope and cost:
LimitDefaultDescription
BudgetSet by caller via graphMaxBudgetMaximum credit cents to spend on company lookups during traversal. The primary control for graph scope.
Max depth10 levelsMaximum depth of shareholder chain to follow
Max entities500Maximum total entities (companies + individuals) in the graph
Execution timeout6 hoursSafety net for stuck traversals — should never be reached in normal operation
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

The metadata.stoppedReason field indicates how the traversal ended:
ReasonMeaning
completedAll shareholder chains were fully resolved
budget_exhaustedThe graphMaxBudget limit was reached
max_depth_reachedMaximum traversal depth was reached
max_nodes_reachedMaximum entity count was reached
timeoutExecution timeout was reached (indicates a system issue)

Response Structure

The graph result is included alongside the standard company data:
{
  "request": {
    "requestId": "uuid-v4",
    "companyId": "36416d",
    "countryCode": "AT",
    "dataStatus": {
      "dataPoints": {
        "graph": { "status": "succeeded" }
      }
    }
  },
  "graph": {
    "nodes": [
      {
        "nodeId": "AT:36416d",
        "type": "company",
        "flags": {
          "isRoot": true,
          "status": "found",
          "isUbo": false
        },
        "company": {
          "legalName": "Example Handels GmbH",
          "countryCode": "AT",
          "id": "36416d"
        }
      },
      {
        "nodeId": "FR:301189718",
        "type": "company",
        "flags": {
          "isRoot": false,
          "status": "found",
          "isUbo": false,
          "isUboProxy": true
        },
        "company": {
          "legalName": "Holding Internationale",
          "countryCode": "FR",
          "id": "301189718"
        },
        "totalOwnershipPercentage": 61
      }
    ],
    "edges": [
      {
        "id": "AT:36416d->FR:301189718",
        "fromId": "AT:36416d",
        "toId": "FR:301189718",
        "percentage": 61,
        "source": "Extracted from trade register extract"
      }
    ],
    "description": "Ownership graph with 2 entities and 1 relationship.",
    "metadata": {
      "stoppedReason": "completed",
      "amountSpent": 200,
      "companiesFetched": 2,
      "companiesSkipped": 0
    }
  }
}

Node Flags

FlagTypeDescription
isRootbooleanThe company that was originally requested
statusstringfound, pending, error, placeholder, search_resolved
isUbobooleanIndividual with >25% direct or indirect ownership
isUboProxybooleanCompany through which UBO ownership flows

Best Practices

The graphMaxBudget parameter is the primary way to control traversal scope. Start with a lower budget for exploration, then increase if you need deeper coverage. Each company lookup costs the standard price for that country.
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.
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 would yield more data.