Skip to main content

Goal

Understand how walls, doors, rooms, and other BIM elements appear in SpeckleSharp so you can filter, extract, and report on connector-published data.

What you will learn

How v3 stores BIM semantics in DataObject.properties, why there are no typed Wall classes, and where proxies fit in.

When to use this

Read this before writing filters or CSV exports on data from Revit, Rhino, ArchiCAD, or other connectors. If you only need a working script, start with Build your first model analysis tool and return here when property names are unclear.
  1. Receive with Receive2
  2. Treat elements as DataObject — check properties, not speckle_type, for BIM meaning
  3. Use Flatten() for model-wide queries
  4. Resolve proxies when you need levels, groups, or instances — see Working with Proxies

Complete example

https://mintcdn.com/speckle/VtRPWzmN-ULoLfIv/images/developers/sdks/csharp.svg?fit=max&auto=format&n=VtRPWzmN-ULoLfIv&q=85&s=f2970e3b8bd4a2c7899b46211a42f251Complete example
using Speckle.Objects.Data;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Extensions;

// After Receive2 — connector data is usually DataObject
var root = await SpeckleBootstrap.Operations.Receive2(/* ... */);

foreach (var obj in root.Flatten().OfType<DataObject>())
{
    Console.WriteLine(obj.name); // "Basic Wall - 200mm"
    Console.WriteLine(obj.speckle_type); // "Objects.Data.DataObject" — same for all BIM elements

    if (obj.properties.TryGetValue("category", out var cat))
        Console.WriteLine($"  category: {cat}");

    // Nested Revit-style parameters
    if (obj.properties["parameters"] is Dictionary<string, object?> paramGroups)
    {
        foreach (var (groupName, group) in paramGroups)
            Console.WriteLine($"  parameter group: {groupName}");
    }
}

// Good — filter by properties
var walls = root.Flatten()
    .OfType<DataObject>()
    .Where(d => d.properties.GetValueOrDefault("category")?.ToString() == "Walls");

// Avoid — speckle_type is not "Wall" or "Door" in v3
// if (obj.speckle_type.Contains("Wall")) { ... }

How it works

v3 object types

In Object Model v3, connectors emit generic containers:
TypeRole
DataObjectBIM element with name, properties, displayValue
CollectionHierarchy (building → level → category)
Geometry (Point, Mesh, …)In displayValue or nested properties
Proxies (GroupProxy, LevelProxy, …)Organisation metadata at the root
BIM semantics live in properties — category, family, type, level, fire rating, Revit parameters, and custom fields.

Deep nesting

Properties can nest several levels:
https://mintcdn.com/speckle/VtRPWzmN-ULoLfIv/images/developers/sdks/csharp.svg?fit=max&auto=format&n=VtRPWzmN-ULoLfIv&q=85&s=f2970e3b8bd4a2c7899b46211a42f251Example
// Direct property
obj.properties["volume"]

// Nested material data (shape varies by connector)
// obj.properties["materials"]["Steel"]["area"]

No typed BIM classes

There is no Wall or Column class in SpeckleSharp for connector data. Use property checks:
https://mintcdn.com/speckle/VtRPWzmN-ULoLfIv/images/developers/sdks/csharp.svg?fit=max&auto=format&n=VtRPWzmN-ULoLfIv&q=85&s=f2970e3b8bd4a2c7899b46211a42f251Example
if (obj.properties.GetValueOrDefault("category")?.ToString() == "Walls")
    Console.WriteLine($"Wall: {obj.name}");

Proxies and hierarchy

Revit levels and groups often appear as proxies at the root, not as parent nodes in the tree. See Working with Proxies and Find objects by property.

Common mistakes

MistakeFix
Looking for speckle_type == "Wall"Filter properties["category"]
Expecting Revit parameter names in UI languageInspect properties keys on a sample object
Ignoring proxies for level-based reportsIndex by applicationId and resolve proxies
Using obj["category"] on all objectsPrefer DataObject.properties for connector data

Next steps

Find objects by property

Traversal and filter recipes

Working with Proxies

Levels, groups, and instances

Export model data to CSV

Door and room schedules
Last modified on July 10, 2026