Data Identities
The Problem​
When you push data from OpenDataDSL to a downstream system via a queue, webhook, or subscription, the item's OpenDataDSL ID is unlikely to match the ID that the target system uses. For example:
- OpenDataDSL ID:
ICE.NBP_M.NBP:SETTLE - SAP commodity ID:
GAS-UK-NBP-01 - Internal ETRM ID:
C2
Without identities, downstream applications must maintain their own mapping tables to translate between OpenDataDSL IDs and their own references — adding complexity and a second source of truth that can drift out of sync.
The Solution​
The identity property on any data item holds a simple key-value map of system names to IDs. When the data is delivered to a downstream system, the identity map travels with it, so the receiving application can look up its own identifier directly from the payload.
data item
└── identity
├── sap → "GAS-UK-NBP-01"
├── molecule → "C2"
└── bloomberg → "NBPGBP Comdty"
The identity property is fully dynamic — you define the system names yourself, and each data item can have as many or as few identities as needed.
Supported Types​
Identities can be added to the following data item types:
| Type | Description |
|---|---|
TimeSeries | Regular time series |
SmartTimeSeries | Derived / calculated time series |
Curve | Forward curve |
SmartCurve | Derived / calculated forward curve |
CurveSeries | Series of curves |
EventTimeSeries | Time series of events |
EventCurve | Curve of events |
Adding Identities​
Smart Curve​
- ODSL
- REST
sc = SmartCurve("AAA_IDENTITY:CURVE", "BASE*1.1")
sc.identity.molecule = "C2"
sc.identity.sap = "S2"
AAA_IDENTITY = Object()
AAA_IDENTITY.SCURVE = sc
save AAA_IDENTITY
POST https://api.opendatadsl.com/api/object/v1
Authorization: Bearer {{token}}
{
"_id": "AAA_IDENTITY",
"SCURVE": {
"_type": "VarSmartCurve",
"expression": "BASE*1.1",
"input": "AAA_IDENTITY:CURVE",
"_identity": {
"molecule": "C2",
"sap": "S2"
}
}
}
TimeSeries​
- ODSL
- REST
ts = TimeSeries("BUSINESS")
ts.identity.molecule = "TS-MOL-01"
ts.identity.sap = "GAS-UK-TS-01"
MY_OBJECT = Object()
MY_OBJECT.PRICE = ts
save MY_OBJECT
POST https://api.opendatadsl.com/api/object/v1
Authorization: Bearer {{token}}
{
"_id": "MY_OBJECT",
"PRICE": {
"_type": "VarTimeSeries",
"calendar": "BUSINESS",
"_identity": {
"molecule": "TS-MOL-01",
"sap": "GAS-UK-TS-01"
}
}
}
Curve​
- ODSL
- REST
ondate = CurveDate(Date("2026-03-02"), "#REOMHENG")
c = Curve(ondate)
c.add("M01", 1.4)
c.add("M02", 2.2)
c.add("M03", 3.3)
c.identity.molecule = "C1"
c.identity.sap = "S1"
AAA_IDENTITY = Object()
AAA_IDENTITY.FORWARD = c
save AAA_IDENTITY
POST https://api.opendatadsl.com/api/object/v1
Authorization: Bearer {{token}}
{
"_id": "AAA_IDENTITY",
"FORWARD": {
"_type": "VarCurve",
"ondate": {
"curveDate": "2024-01-15",
"expiryCalendar": "#REOMHENG"
},
"contracts": [
{"tenor": "M01", "value": 1.4},
{"tenor": "M02", "value": 2.2},
{"tenor": "M03", "value": 3.3}
],
"_identity": {
"molecule": "FWD-MOL-01",
"bloomberg": "NBPGBP Comdty"
}
}
}
Smart TimeSeries​
- ODSL
- REST
st = SmartTimeSeries("MY_BASE_TS:PRICE", "BASE*1.05")
st.identity.sap = "DERIVED-SAP-ID"
st.identity.etrm = "ETRM-REF-99"
MY_OBJECT = Object()
MY_OBJECT.DERIVED = st
save MY_OBJECT
POST https://api.opendatadsl.com/api/object/v1
Authorization: Bearer {{token}}
{
"_id": "MY_OBJECT",
"DERIVED": {
"_type": "VarSmartTimeSeries",
"input": "MY_BASE_TS:PRICE",
"expression": "BASE*1.05",
"_identity": {
"sap": "DERIVED-SAP-ID",
"etrm": "ETRM-REF-99"
}
}
}
The system names you use as keys — sap, molecule, bloomberg, etrm — are entirely up to you. Use names that are meaningful to your team and consistent across your data objects.
Reading Identities​
- ODSL
- REST
// Read the full identity map
item = ${data:"MY_OBJECT:SCURVE"}
print item.identity
// Read a specific system's identity
print item.identity.sap
// Read the full data item — identity is included in the response
GET https://api.opendatadsl.com/api/data/v1/private/MY_OBJECT:SCURVE
Authorization: Bearer {{token}}
Searching Using an Identity​
You can search for data items by matching against an identity value using the find command:
- ODSL
- REST
ts = find ${data} where _identity.molecule="C1"
GET https://api.opendatadsl.com/api/data/v1/private?_filter={"_identity.molecule":"C1"}
Authorization: Bearer {{token}}
This returns all data items where the molecule identity key equals "C1", regardless of their OpenDataDSL ID. This is particularly useful when you know the downstream system's identifier but not the native OpenDataDSL path.
Retrieving a TimeSeries by Identity​
You can retrieve a time series directly using an identity value as the lookup key:
- ODSL
- REST
ts1 = ${data:"private.identity.molecule"/"test"}
GET https://api.opendatadsl.com/api/data/v1/private.identity.molecule/test
Authorization: Bearer {{token}}
The path format is "private.identity.<key>"/"<value>", where:
<key>is the identity system name (e.g.molecule,sap)<value>is the identifier you are looking up
Retrieving a Curve by Identity​
You can retrieve a curve using an identity value, with an optional _ondate parameter to specify the curve date:
- ODSL
- REST
c1a = ${data:"private.identity.molecule"/"C1","_ondate=2026-03-02"}
GET https://api.opendatadsl.com/api/data/v1/private.identity.molecule/C1?_ondate=2026-03-02
Authorization: Bearer {{token}}
The same "private.identity.<key>"/"<value>" path format applies. Add _ondate=<date> to retrieve the curve as of a specific date.
Updating Identities​
- ODSL
- REST
To update or add an identity on an existing data item, fetch the raw data item, set the new value, and save it back:
// Fetch the data item with raw flag to preserve identity data
obj = ${object:"AAA_IDENTITY", "_raw=true"}
// Add or update a single identity
obj.SCURVE.identity.bloomberg = "NEW-BLOOMBERG-ID"
save obj
To add/update an identity key, use the identity function with the PUT action:
PUT https://api.opendatadsl.com/api/data/v1/private?_function=identity
Authorization: Bearer {{token}}
{
"action":"PUT",
"data": [
"_id":"AAA_IDENTITY:SCURVE",
"bloomberg":"NEW-BLOOMBERG-ID"
]
}
- ODSL
- REST
To remove an identity key, use the .remove() method:
obj = ${object:"AAA_IDENTITY", "_raw=true"}
obj.SCURVE.identity.remove("bloomberg")
save obj
To remove an identity key, use the identity function with the DELETE action:
PUT https://api.opendatadsl.com/api/data/v1/private?_function=identity
Authorization: Bearer {{token}}
{
"action":"DELETE",
"_id": ["AAA_IDENTITY:SCURVE"],
"identity":["bloomberg"]
}
Identities in Downstream Delivery​
When a subscription delivers data to a queue, webhook, or script target, the _identity map is included in the message payload. The receiving system can read its own key directly, with no external mapping table required.
Example queue message payload (JSON)​
{
"_id": "AAA_IDENTITY:SCURVE",
"_type": "VarSmartCurve",
"expression": "BASE*1.1",
"_identity": {
"molecule": "C2",
"sap": "S2"
}
}
Reading the identity in a receiving script​
If your subscription uses a Script target, you can access the identity directly:
// input.data contains the delivered data item
item = input.data
sapId = item.identity.sap
print "Delivering to SAP with ID: " + sapId
Reading the identity in a Mustache template​
If your subscription uses an Email, Webhook, or Queue target with a Mustache template, reference identities using standard Mustache syntax:
<p>SAP ID: {{identity.sap}}</p>
<p>Molecule ID: {{identity.molecule}}</p>
Multiple Data Items on One Object​
A single master data object often holds several data items, each with their own identities:
- ODSL
- REST
MY_OBJECT = Object()
ts = TimeSeries("BUSINESS")
ts.identity.molecule = "TS-MOL-01"
ts.identity.sap = "GAS-UK-TS-01"
MY_OBJECT.PRICE = ts
c = Curve(ondate)
c.identity.molecule = "FWD-MOL-01"
c.identity.bloomberg = "NBPGBP Comdty"
MY_OBJECT.FORWARD = c
save MY_OBJECT
PUT https://api.opendatadsl.com/api/object/v1
Authorization: Bearer {{token}}
{
"_id": "MY_OBJECT",
"PRICE": {
"_type": "VarTimeSeries",
"calendar": "BUSINESS",
"_identity": {
"molecule": "TS-MOL-01",
"sap": "GAS-UK-TS-01"
}
},
"FORWARD": {
"_type": "VarCurve",
"ondate": "2024-01-15",
"_identity": {
"molecule": "FWD-MOL-01",
"bloomberg": "NBPGBP Comdty"
}
}
}
Each data item carries its own independent identity map, so downstream systems receiving either item can resolve their own identifier without any additional configuration.
Further Reading​
- Extracting Data — overview of all data delivery methods including automations
- Automation REST service — full automation reference
- SmartCurve variable reference
- TimeSeries variable reference