Entity structure

OpenSanctions uses the FollowTheMoney data model to structure its entity graph. Below is an explanation of how entities and their relationships are designed.

FollowTheMoney (FtM) defines a simple data model for storing complex object graphs. You will need to understand three concepts: entities, entity references, and entity streams.


Entities are often expressed as snippets of JSON, with three standard fields: a unique id, a specification of the type of the entity called schema, and a set of properties. All properties are multi-valued and values are always strings.

    "id": "1b38214f88d139897bbd13eabde464043d84bbf9",
    "schema": "Person",
    "properties": {
        "name": ["John Doe"],
        "nationality": ["us", "au"],
        "birthDate": ["1982"]

What properties can be set for an entity is determined by it's schema. For example, a Person has a nationality, while a Company allows for setting a jurisdiction. Both properties, however, have the same property type, country. You can see a full listing of the available schemata and their properties in the data dictionary.


Entities can reference other entities. This is achieved via a special property type, entity. Properties of this type simply store the ID of another entity. For example, a Passport entity can be linked to a Person entity via its holder property:

    "id": "passport-entity-id",
    "schema": "Passport",
    "properties": {
        "holder": ["person-entity-id"],
        "number": ["CJ 7261817"]

Interstitial entities

A link between two entities will have its own attributes. For example, an investigator looking at a person that owns a company might want to know when that interest was acquired, and also what percentage of shares the person holds.

This is addressed by making interstitial entities. In the example above, an Ownership entity would be created, with references to the person as its owner property and to the company as its asset property. That entity can then define further properties, including startDate and percentage:

    "id": "ownership-entity-id",
    "schema": "Ownership",
    "properties": {
        "owner": ["person-entity-id"],
        "asset": ["company-entity-id"],
        "startDate": ["2020-01-01"],
        "percentage": ["51%"],

Note: It is tempting to simplify this model by assuming that entities derived from Thing are node entities, and those derived from Interval are edges. This assumption is false and will lead to nasty bugs in your code.


Many tools in the FtM ecosystem use streams of entities to transfer or store information. Entity streams are simply sequences of entity objects that have been serialised to JSON as single lines without any indentation, each entity separated by a newline.

Entity streams are read and produced by virtually every part of the FollowTheMoney command-line, OpenSanctions, and the Aleph platform. When stored to disk as a file, the extensions .ftm or .ijson should be used.

Got more questions? Join the Slack chat to ask questions and get support. You can also book an hour of consulting time to discuss technical questions with the team.