The Object Model (L2)
The Data Domain (L1) defines the organisation's object types, business terms, relationships, and governance. The Object Model is the use-case layer above it. It pins the data-domain snapshots used by the use case, gives the participating object types local role names, selects the relationships that connect those roles, and narrows governance for specific business-term paths.
What an Object Model Does
An Object Model is a tenant-owned, versioned use-case curation over one or more published data domains.
Data-domain snapshots are pinned. domainRefs contains at most one reference per data domain. Each reference includes dataDomainId and dataDomainVersion, so resolution always reads the intended snapshot.
Roles bind object types to use-case participants. A role has an object-model-local id and name, and its entity identifies an object type with { dataDomainId, entity }. specializes can add specialization object types to the role. In this walkthrough, the employee role binds to Person and applies the Employee specialization, while employer binds to Organization and applies Employer.
Relationships are selected from the data domain. Each relationships entry names a data-domain relationship with { dataDomainId, relationship }. The relationship type and its ends remain defined by the data domain. The object model selects which relationships participate in the use case.
Overrides are narrow-only. An overrides entry is keyed by { roleRef, path } and can tighten conformance, sdPolicy, cardinality, entryCodesSubset, or sensitive. It cannot widen the effective governance established by the referenced data domain.
The Object Model defines the effective use-case graph. The Data Product (L3) later selects the business-term paths that a particular output needs.
Create, Configure, Publish, and Resolve the Object Model
The example Object Model uses two data-domain object types and two relationships:
employeebinds toPersonand applies theEmployeespecialization.employerbinds toOrganizationand applies theEmployerspecialization.residentialAddressandemploymentare selected from the pinned data domain.emailis tightened fromOPTIONALtoMANDATORYfor theemployeerole.
Create
- Request
- Response
POST /api/model/v1/objects
{
"name": "Acme Employee Onboarding",
"description": "Use-case object model for employee onboarding and badge issuance.",
"domainRefs": [
{
"dataDomainId": "9f2c1b3e-7a44-4c1e-8b0a-2d6f5e9c1a77",
"dataDomainVersion": 3
}
],
"roles": [
{
"id": "employee",
"name": "Employee",
"entity": {
"dataDomainId": "9f2c1b3e-7a44-4c1e-8b0a-2d6f5e9c1a77",
"entity": "Person"
},
"specializes": ["Employee"],
"description": "The employee participant in the use case."
},
{
"id": "employer",
"name": "Employer",
"entity": {
"dataDomainId": "9f2c1b3e-7a44-4c1e-8b0a-2d6f5e9c1a77",
"entity": "Organization"
},
"specializes": ["Employer"]
}
],
"relationships": [
{
"dataDomainId": "9f2c1b3e-7a44-4c1e-8b0a-2d6f5e9c1a77",
"relationship": "residentialAddress"
},
{
"dataDomainId": "9f2c1b3e-7a44-4c1e-8b0a-2d6f5e9c1a77",
"relationship": "employment"
}
],
"overrides": [
{
"roleRef": "employee",
"path": ["email"],
"conformance": "MANDATORY"
}
]
}
201 Created returns an ObjectModel. The server assigns id, starts version at 1, and creates the model with status: "DRAFT".
{
"id": "c4d5e6f7-8a9b-4c0d-8e1f-2a3b4c5d6e7f",
"tenantId": "acme",
"name": "Acme Employee Onboarding",
"version": 1,
"status": "DRAFT",
"domainRefs": [
{
"dataDomainId": "9f2c1b3e-7a44-4c1e-8b0a-2d6f5e9c1a77",
"dataDomainVersion": 3
}
],
"roles": [
{
"id": "employee",
"name": "Employee",
"entity": {
"dataDomainId": "9f2c1b3e-7a44-4c1e-8b0a-2d6f5e9c1a77",
"entity": "Person"
},
"specializes": ["Employee"]
}
],
"relationships": [
{
"dataDomainId": "9f2c1b3e-7a44-4c1e-8b0a-2d6f5e9c1a77",
"relationship": "residentialAddress"
}
],
"overrides": [
{
"roleRef": "employee",
"path": ["email"],
"conformance": "MANDATORY"
}
],
"description": "Use-case object model for employee onboarding and badge issuance.",
"createdAt": "2026-01-15T09:30:00Z",
"updatedAt": "2026-01-15T09:30:00Z"
}
Field reference
| Field | Meaning |
|---|---|
domainRefs | Data-domain snapshot references. Each data domain can appear at most once. |
roles[].id | Object-model-local role identifier. It is used by relationships, overrides, and downstream data-product paths. |
roles[].name | Human-readable role name. |
roles[].entity | { dataDomainId, entity }, identifying the bound data-domain object type. |
roles[].specializes | Specialization object-type names applied to the bound object type. |
relationships[] | { dataDomainId, relationship }, selecting a data-domain relationship type. |
overrides[] | Narrow-only governance entries keyed by a role and path. Supported fields are conformance, sdPolicy, cardinality, entryCodesSubset, and sensitive. |
Configure the draft
The create request accepts all four structural collections. A draft can also be updated through dedicated replacement endpoints:
PUT /api/model/v1/objects/{objectModelId}/domain-refs
{
"domainRefs": [
{
"dataDomainId": "9f2c1b3e-7a44-4c1e-8b0a-2d6f5e9c1a77",
"dataDomainVersion": 3
}
]
}
PUT /api/model/v1/objects/{objectModelId}/roles
PUT /api/model/v1/objects/{objectModelId}/relationships
PUT /api/model/v1/objects/{objectModelId}/overrides
Each endpoint replaces its corresponding collection. The request bodies are respectively { "roles": [...] }, { "relationships": [...] }, and { "overrides": [...] }. The object model must be in DRAFT for authoring changes.
Use PATCH /api/model/v1/objects/{objectModelId} for the mutable name and description fields. Use POST /api/model/v1/objects/{objectModelId}/version with no request body to increment the snapshot version.
Publish
The lifecycle has two values: DRAFT and PUBLISHED. Set the status with:
- Request
- Response
PUT /api/model/v1/objects/{objectModelId}/status
{ "status": "PUBLISHED" }
200 OK returns the updated ObjectModel with the requested lifecycle status. A published model is the frozen snapshot that downstream data products can reference.
{
"id": "c4d5e6f7-8a9b-4c0d-8e1f-2a3b4c5d6e7f",
"version": 1,
"status": "PUBLISHED"
}
Resolve
Resolve the model against its pinned data-domain snapshots:
GET /api/model/v1/objects/{objectModelId}/resolved
200 OK returns a ResolvedObjectModel. Resolution applies role specializations, projects the selected relationships, and folds the object-model overrides into each effective business-term overlay.
{
"objectModelId": "c4d5e6f7-8a9b-4c0d-8e1f-2a3b4c5d6e7f",
"objectModelVersion": 1,
"domainRefs": [
{
"dataDomainId": "9f2c1b3e-7a44-4c1e-8b0a-2d6f5e9c1a77",
"dataDomainVersion": 3
}
],
"roles": [
{
"id": "employee",
"entity": "Person",
"specializes": ["Employee"],
"partyType": "natural_person",
"attributes": [
{
"path": ["given_name"],
"valueType": "Text",
"sourceEntity": "Person",
"overlays": { "conformance": "OPTIONAL" }
}
]
}
],
"relationships": [
{
"name": "residentialAddress",
"relationType": "has-address",
"sourceRole": "employee",
"targetEntity": "Address",
"targetAttributes": []
}
],
"schemaRelationships": []
}
The resolved role attributes include terms inherited through specializes. A relationship traversal can resolve a term such as ["residentialAddress", "country"] from the employee role into the related Address object type.
Generate a JSON Schema
The object model can produce a JSON Schema from its resolved shape. The current generation operation supports JSON_SCHEMA as its targetType.
POST /api/model/v1/objects/{objectModelId}/schemas
{
"targetType": "JSON_SCHEMA",
"register": false
}
The response is a GeneratedObjectModelSchemaResult containing objectModelId, objectModelVersion, targetType, the serialized schema, and a nullable schemaId. When register is true, schemaId identifies the registered schema.
Narrowing and Version Pinning
The effective model is resolved in this order:
- Data Domain (L1) establishes the canonical object types, business terms, relationships, and governance overlays.
- Object Model (L2) binds roles and relationships and applies its narrow-only overrides.
- Data Product (L3) selects paths and can narrow the selected terms further.
- Channel (L4) maps selected paths to an output and does not change model governance.
domainRefs makes the first step deterministic. A downstream data product pins the Object Model with objectModelRef: { objectModelId, objectModelVersion }, so it continues to resolve against the intended snapshot.
License
The semantic-model authoring API is gated by the semantic-modeling.v1 enterprise feature. Every request in this walkthrough uses an operator bearer token, and the tenant context is resolved from that token.
Authorization: Bearer <operator access token>
Content-Type: application/json
Next Steps
- Data Product (L3): pin this published Object Model and select role-rooted traversal paths.
- Modeling Your World: review the four-layer model, governance, and version pinning.
- Data Domain (L1): author the object types, business terms, relationships, and governance that this Object Model composes.