---
title: "How do I create a custom data type and store reference data?"
slug: "how-do-i-create-a-custom-data-type-and-store-reference-data"
updated: 2024-11-27T16:07:18Z
published: 2024-11-27T16:07:18Z
canonical: "support.lusid.com/how-do-i-create-a-custom-data-type-and-store-reference-data"
---

> ## Documentation Index
> Fetch the complete documentation index at: https://support.lusid.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How do I create a custom data type and store reference data?

Providing you are a LUSID user with sufficient [access control permissions](/v1/docs/introduction-to-identity-management-and-access-control), you can create a custom data type to extend LUSID's [built-in data types](/v1/docs/what-is-a-data-type).

You can use your custom data type to:

- Constrain the values that users are allowed to assign to [properties](/v1/docs/introduction-to-properties) of this data type. For example, you could create an `Exchange` data type that only allows a user to enter recognised market identifier codes for a particular transaction property.
- Store additional reference data against the set of allowed values for properties of this data type. For example, you could create a `NaceCode` data type that simultaneously constrains the user to only entering recognised NACE codes, and additionally stores the full activity definition for each code (see the example below). This means you don't have to create additional properties to store this information.

> **Note:** If you are the LUSID domain owner, you are automatically assigned the built-in `lusid-administrator` role, which has all the permissions necessary to perform the operations in this article.

## Using the LUSID REST API

1. [Obtain an API access token](/v1/docs/how-do-i-obtain-and-use-a-short-lived-api-access-token-from-okta).
2. Call the LUSID [CreateDataType](https://www.lusid.com/docs/api#operation/CreateDataType) API, passing in your API access token and a suitable definition for the data type. For example, the following snippet creates a data type that constrains, describes and extends the first five NACE codes:

```json
curl -X POST "https://<your-domain>.lusid.com/api/api/datatypes"
   -H "Authorization: Bearer <your-API-access-token>"
   -H "Content-Type: application/json-patch+json"
   -d '{
  "scope": "industry",
  "code": "naceCode",
  "typeValueRange": "Closed",
  "displayName": "NACE Code",
  "description": "Statistical classification of economic activities in the European Community",
  "valueType": "String",
  "referenceData": {
    "fieldDefinitions": [
      {
        "key": "description",
        "isRequired": true,
        "isUnique": false
      },
      {
        "key": "sectionCode",
        "isRequired": true,
        "isUnique": false
      },
      {
        "key": "sectionDescription",
        "isRequired": true,
        "isUnique": false
      },
      {
        "key": "divisionCode",
        "isRequired": false,
        "isUnique": false
      },
      {
        "key": "divisionDescription",
        "isRequired": false,
        "isUnique": false
      },
      {
        "key": "groupCode",
        "isRequired": false,
        "isUnique": false
      },
      {
        "key": "groupDescription",
        "isRequired": false,
        "isUnique": false
      },
      {
        "key": "classCode",
        "isRequired": false,
        "isUnique": true
      },
      {
        "key": "classDescription",
        "isRequired": false,
        "isUnique": true
      }
    ],
    "values": [
      {
        "value": "A",
        "fields": {
          "description": "Agriculture, forestry and fishing",
          "sectionCode": "A",
          "sectionDescription": "Agriculture, forestry and fishing"
        }
      },
      {
        "value": "01",
        "fields": {
          "description": "Crop and animal production, hunting and related service activities",
          "sectionCode": "A",
          "sectionDescription": "Agriculture, forestry and fishing",
          "divisionCode": "01",
          "divisionDescription": "Crop and animal production, hunting and related service activities"
        }
      },
      {
        "value": "011",
        "fields": {
          "description": "Growing of non-perennial crops",
          "sectionCode": "A",
          "sectionDescription": "Agriculture, forestry and fishing",
          "divisionCode": "01",
          "divisionDescription": "Crop and animal production, hunting and related service activities",
          "groupCode": "011",
          "groupDescription": "Growing of non-perennial crops"
        }
      },
      {
        "value": "0111",
        "fields": {
          "description": "Growing of cereals (except rice), leguminous crops and oil seeds",
          "sectionCode": "A",
          "sectionDescription": "Agriculture, forestry and fishing",
          "divisionCode": "01",
          "divisionDescription": "Crop and animal production, hunting and related service activities",
          "groupCode": "011",
          "groupDescription": "Growing of non-perennial crops",
          "classCode": "0111",
          "classDescription": "Growing of cereals (except rice), leguminous crops and oil seeds"
        }
      },
      {
        "value": "0112",
        "fields": {
          "description": "Growing of rice",
          "sectionCode": "A",
          "sectionDescription": "Agriculture, forestry and fishing",
          "divisionCode": "01",
          "divisionDescription": "Crop and animal production, hunting and related service activities",
          "groupCode": "011",
          "groupDescription": "Growing of non-perennial crops",
          "classCode": "0112",
          "classDescription": "Growing of rice"
        }
      }
    ]
  }
}'
```

Note the following about `NaceCode`:

- Specifying a `typeValueRange` of `Closed` constrains the user to only entering allowed values (see below) for properties of this data type. The opposite value (`Open`) allows the user to enter any value.
- Since `valueType` is a `String`, `unitSchema` and `acceptableUnits` are not required.
- Since `typeValueRange` is `Closed` and we're defining `referenceData`, `acceptableValues` are not required (the reference data becomes the allowed values).
- The `fieldDefinitions` define the quality and quantity of reference data fields.
- For each item of reference data in values:
  - `value` defines the allowed value the user is able to enter for properties of this data type.
  - `fields` define the actual reference data to store against the value, where each field value is mandatory and/or unique according to its `fieldDefinition`.

## Using Luminesce

You can use the [Lusid.DataType.Writer](/v1/docs/lusiddatatypewriter) provider.
