Skip to main content
Now that you understand the concepts, let’s examine the technical structure of objects. Every object in Speckle follows a consistent data model, regardless of which connector created it.

Base Object Fields

All Speckle objects inherit from Base and have these core fields:
{
  "id": "string (hash-based, immutable)",
  "speckle_type": "string (type identifier)",
  "applicationId": "string (source application identifier)"
}

id

The id is a content-based hash that uniquely identifies the object’s data. If two objects have the same content, they have the same id. This enables efficient deduplication and version control.

speckle_type

The speckle_type identifies what kind of object this is. Examples:
  • "Objects.Geometry.Point"
  • "Objects.Geometry.Mesh"
  • "Objects.Data.DataObject"
  • "Objects.Data.DataObject:Objects.Data.RevitObject"

applicationId

The applicationId is the identifier from the source application (e.g., a Revit element ID, a Rhino object GUID). This is how proxies reference objects.

DataObject Structure

DataObject is the most common object type for BIM elements. It extends Base with these fields:
{
  "id": "string",
  "speckle_type": "Objects.Data.DataObject",
  "applicationId": "string",
  "name": "string",
  "properties": {
    "string": "any value"
  },
  "displayValue": [
    "Base (geometry objects)"
  ],
  "units": "string"
}

name

A human-readable name for the object (e.g., “Basic Wall - 200mm”, “Column A1”).

properties

A dictionary of key-value pairs containing all metadata about the object. This is where connector-specific data lives:
  • Revit: Instance parameters, type parameters, material quantities
  • Rhino: User strings, user dictionaries
  • AutoCAD: Extension dictionaries, XData
The properties dictionary can contain nested structures, but the values are always JSON-serializable.

displayValue

An array of geometry objects that represent the visual appearance of this DataObject. Geometry objects (Point, Line, Mesh, Brep, etc.) are stored here, not as direct children.
DataObject
└── displayValue: [
      Mesh (visual representation),
      Line (edge curves),
      ...
    ]

units

The unit system used for this object’s geometry (e.g., "meters", "feet", "millimeters").

Geometry Object Structure

Geometry objects are simpler—they represent pure geometric primitives:
{
  "id": "string",
  "speckle_type": "Objects.Geometry.Mesh",
  "applicationId": "string (optional)",
  "vertices": [...],
  "faces": [...],
  "units": "string"
}
Geometry objects don’t have properties or displayValue—they are the geometry themselves.

Instance Structure

Instance objects represent block references or instanced geometry:
{
  "id": "string",
  "speckle_type": "Objects.Instance",
  "applicationId": "string",
  "definitionId": "string (applicationId of Definition proxy)",
  "transform": "Matrix (4x4 transformation)",
  "units": "string"
}
The definitionId references a Definition proxy that contains the actual geometry.

Global Invariants

These rules apply to all objects:
  1. No nested DataObjects - DataObjects cannot contain other DataObjects as direct children. Use displayValue for geometry, and use proxies for relationships.
  2. Geometry always in displayValue - All visual geometry for a DataObject must be in the displayValue array, not as direct properties.
  3. Objects always have core fields - Every object has id, speckle_type, applicationId, units, and (for DataObjects) properties.
  4. Proxies reference by applicationId - Proxies link to objects using applicationId, not id.
  5. Hierarchy is Speckle-imposed - The collection hierarchy is created by Speckle connectors, not necessarily matching the source application’s structure exactly.
This design prevents deep nesting and keeps the data model flat and predictable. If you need to represent a hierarchical relationship (like a wall containing studs), use:
  1. Separate DataObjects in collections
  2. Proxies to encode the relationship
  3. Properties to store references
This makes traversal and processing much simpler.
  • id: Speckle’s content-based hash. Same content = same id. Used for deduplication and versioning.
  • applicationId: The source application’s identifier (Revit element ID, Rhino GUID, etc.). Used for references and proxies. Can change if the object is modified in the source application.
You use id to track objects across versions. You use applicationId to link objects to their source and to resolve proxy references.

Connector-Specific Extensions

Some connectors extend DataObject with additional fields. For example:
  • RevitObject: Adds type, family, category, level, location
  • NavisworksObject: Minimal extension (just inherits DataObject)
  • Civil3dObject: Adds baseCurves
These extensions are documented in the connector pages.

Example: Complete DataObject

Here’s a realistic example of a Revit wall object:
{
  "id": "a1b2c3d4e5f6...",
  "speckle_type": "Objects.Data.DataObject:Objects.Data.RevitObject",
  "applicationId": "12345",
  "name": "Basic Wall - 200mm",
  "properties": {
    "Volume": 12.5,
    "Area": 45.2,
    "Material": "Concrete",
    "Type Parameters": {
      "Width": 0.2,
      "Function": "Exterior"
    }
  },
  "displayValue": [
    {
      "speckle_type": "Objects.Geometry.Mesh",
      "vertices": [...],
      "faces": [...]
    }
  ],
  "type": "Basic Wall",
  "family": "Basic Wall",
  "category": "Walls",
  "level": "Level 1",
  "units": "meters"
}

Next Steps