Views:

LUSID has a set of built-in entities that represent real-world objects core to the task of managing investment data, such as portfolios, instruments and transactions.

You can create custom entities to model real-world objects and concepts that LUSID does not natively represent. Please note custom entities are not feature-complete yet.

The first task is to create a custom entity type and then a property definition that constitutes a unique identifier for this type. You can then create as many custom entity instances of the type as you need, supplying a unique identifier value for each.

Note that LUSID stores your custom entity data bitemporally and you can retrieve it using the effective-at or as-at timelines in the same way as built-in entity data. You can also create relationships between custom entities and built-in entities. However, LUSID does not know how to interpret your custom entity data. It cannot be used to inform holding calculations or valuation operations.

Defining a custom entity type

You can call the LUSID CreateCustomEntityDefinition API to create a custom entity type, specifying a unique name for the type and defining its data fields. Note that LUSID automatically prefixes the entity type name with a ~ to distinguish it from current or future built-in entity types.

Data fields are not the same as properties. They can either be Perpetual or TimeVariant (that is, expected to change), but the data types are restricted to String, Boolean, DateTime and Decimal. Unlike properties, data fields cannot be scoped (that is, entitled) independently of parent custom entities.

For example, you could create a custom entity type to represent the concept of office locations:

curl -X POST "https://<your-domain>.lusid.com/api/api/customentities/entitytypes"
 -H "Authorization: Bearer <your-API-access-token>"
 -H "Content-Type: application/json-patch+json"
 -d '
{
  "entityTypeName": "Office",
  "displayName": "Office location",
  "description": "An office or branch location",
  "fieldSchema": [
    {
      "name": "streetAddress",
      "lifetime": "Perpetual",
      "type": "String",
      "required": false
    },
    {
      "name": "postalCode",
      "lifetime": "Perpetual",
      "type": "String",
      "required": false
    },
    {
      "name": "seatingCapacity",
      "lifetime": "TimeVariant",
      "type": "Decimal",
      "required": false
    },
    {
      "name": "isHeadOffice",
      "lifetime": "TimeVariant",
      "type": "Boolean",
      "required": true
    }
  ]
}'


Note the response identifies the entity type as ~Office:

{
    "href": "https://jamleed.lusid.com/api/api/customentities/entitytypes",
    "entityTypeName": "Office",
    "displayName": "Office location",
    "description": "An office or branch location",
    "entityType": "~Office",
    "fieldSchema": [
        {
            "name": "isHeadOffice",
            "lifetime": "TimeVariant",
            "type": "Boolean",
            "required": true
        },
        {
            "name": "postalCode",
            "lifetime": "Perpetual",
            "type": "String",
            "required": false
        },
        {
            "name": "seatingCapacity",
            "lifetime": "TimeVariant",
            "type": "Decimal",
            "required": false
        },
        {
            "name": "streetAddress",
            "lifetime": "Perpetual",
            "type": "String",
            "required": false
        }
    ]
}

Creating a property definition to constitute a unique identifier

The next step is to create a custom property definition in the standard way using the LUSID CreatePropertyDefinition API. The domain field must be set to CustomEntity and the constraintStyle field to Identifier (highlighted in red below).

For example, the following call creates a property definition with a 3-stage property key of CustomEntity/demoScope/officeId:

curl -X POST "https://<your-domain>.lusid.com/api/api/propertydefinitions"
 -H "Authorization: Bearer <your-API-access-token>"
 -H "Content-Type: application/json-patch+json"
 -d '
 {
  "domain": "CustomEntity",
  "scope": "demoScope",
  "code": "officeId",
  "displayName": "Office ID",
  "dataTypeId": {
    "scope": "system",
    "code": "string"
  },
  "lifeTime": "Perpetual",
  "constraintStyle": "Identifier",
  "description": "Identifier property used to identify custom entities of type ~Office"
 }'

Creating a custom entity with a unique identifier value

You can now call the LUSID UpsertCustomEntity API as many times as you need to create a custom entity instance of the custom entity type (remember to prefix the type name with ~).

Each custom entity must have a unique identifierValue. The identifierScope must match the scope of the property definition created above, and the identifierType must match the code (highlighted in red below): 

curl -X POST "https://<your-domain>.lusid.com/api/api/customentities/~Office"
 -H "Authorization: Bearer <your-API-access-token>"
 -H "Content-Type: application/json-patch+json"
 -d '
{
  "displayName": "One Carter Lane",
  "description": "FINBOURNE Technology's London Office",
  "identifiers": [
    {
      "identifierScope": "demoScope",
      "identifierType": "officeId",

      "identifierValue": "one_carter_lane"
    }
  ],
  "fields": [
    {
      "name": "streetAddress",
      "value": "One Carter Lane, London"
    },
    {
      "name": "postalCode",
      "value": "EC4V 5ER"
    },
    {
      "name": "seatingCapacity",
      "value": 150,
      "effectiveFrom": "2021-08-01T00:00:00.00Z"
    },
    {
      "name": "isHeadOffice",
      "value": true,
      "effectiveFrom": "2021-08-01T00:00:00.00Z"
    }
  ]
}'


The response confirms the date ranges that custom entity values are valid between:

{
  "href": "https://<your-domain>.lusid.com/api/api/customentities/~Office",
  "entityType": "~Office",
  "version": {
    "effectiveFrom": "0001-01-01T00:00:00.0000000+00:00",
    "asAtDate": "2022-05-18T06:55:11.3172620+00:00"
  },
  "displayName": "One Carter Lane",
  "description": "FINBOURNE Technology's London Office",
  "identifiers": [
    {
      "identifierScope": "demoScope",
      "identifierType": "officeId",
      "identifierValue": "one_carter_lane",
      "effectiveFrom": "0001-01-01T00:00:00.0000000+00:00",
      "effectiveUntil": "9999-12-31T23:59:59.9999999+00:00"
    }
  ],
  "fields": [
    {
      "name": "isHeadOffice",
      "value": true,
      "effectiveFrom": "2021-08-01T00:00:00.0000000+00:00",
      "effectiveUntil": "9999-12-31T23:59:59.9999999+00:00"
    },
    {
      "name": "postalCode",
      "value": "EC4V 5ER",
      "effectiveFrom": "0001-01-01T00:00:00.0000000+00:00",
      "effectiveUntil": "9999-12-31T23:59:59.9999999+00:00"
    },
    {
      "name": "seatingCapacity",
      "value": 150,
      "effectiveFrom": "2021-08-01T00:00:00.0000000+00:00",
      "effectiveUntil": "9999-12-31T23:59:59.9999999+00:00"
    },
    {
      "name": "streetAddress",
      "value": "One Carter Lane, London",
      "effectiveFrom": "0001-01-01T00:00:00.0000000+00:00",
      "effectiveUntil": "9999-12-31T23:59:59.9999999+00:00"
    }
  ],
  ...
}

Retrieving custom entities you have created

You can retrieve a particular custom entity using the LUSID GetCustomEntity API.

You can retrieve all the custom entities of a particular type using the LUSID ListCustomEntities API, or perform a filter operation to only retrieve a matching set. Custom entities support filtering on data field values using the fields keyword, for example:

curl -X GET "https://<your-domain>.lusid.com/api/api/customentities/~Office?filter=fields[streetAddress] startswith 'One'"
 -H "Authorization: Bearer <your-API-access-token>"


Note if you create relationships between a custom entity and other entities you can retrieve them using the LUSID GetCustomEntityRelationships API.

A note on unsupported features

Custom entities are in the early phase of their development and do not yet support:

  • Entitlement checking. 
  • Properties. 
  • Updating a custom entity type definition.
  • Deleting a custom entity type definition. 
  • Identifier properties that are specific to the custom entity type (identifier properties in the CustomEntity domain can currently be applied to custom entity instances of any type).