TBH i wouldnt try to download a stream with the REST API from python, id go straight to using specklepy.
Some basic setup
import os
from dotenv import load_dotenv
load_dotenv()
token = os.getenv("SPECKLE_APP_TOKEN")
server = os.getenv("SPECKLE_APP_URL")
project_id = "6a87e55c77"
Get an authenticated client
from specklepy.api.client import SpeckleClient
client = SpeckleClient(server, use_ssl=True)
client.authenticate_with_token(token)
Use the API to retrieve data using a ServerTransport
from specklepy.transports.memory import MemoryTransport
from specklepy.transports.server import ServerTransport
project = client.stream.get(project_id)
model_id = "58c8effef5"
branches = client.branch.list(project_id)
model = next((b for b in branches if b.id == model_id), None)
latest_version = model.commits.items[0].referencedObject
memory_transport: MemoryTransport = MemoryTransport()
server_transport = ServerTransport(project_id, client)
data = operations.receive(latest_version, server_transport, memory_transport)
A simple flatten function to retrieve a List and not a Graph
from collections.abc import Iterable
from specklepy.objects import Base
def flatten_base(base: Base) -> Iterable[Base]:
"""Flatten a base object into an iterable of bases.
This function recursively traverses the `elements` or `@elements` attribute of the
base object, yielding each nested base object.
Args:
base (Base): The base object to flatten.
Yields:
Base: Each nested base object in the hierarchy.
"""
# Attempt to get the elements attribute, fallback to @elements if necessary
elements = getattr(base, "elements", getattr(base, "@elements", None))
if elements is not None:
for element in elements:
yield from flatten_base(element)
yield base
Thank you very much Jonathan! this is very helpfull. I tried this as well in dynamo for Revit. The problem i have here happens at the statement:
project = client.stream.get(project_id)``
Giving the output:
Failed to execute the GraphQL stream request. Inner exception: Transport is allready connected.
Before we start to tackle this problem, maybe it would be helpfull to explain a bit off what im trying to do. I want to make a custom connector In Revit/Dynamo which will be able to get elements in an sends them back with the same id. The goal is to maintain the element traceability throughout the whole proces, even when it gets modified in different software. The documentation stated:
When working with uploading and downloading objects, the REST API is preferred.
Is the GrapQL the right approach for this usecase or is the REST API the way to go for this usecase? I’m still figuring out the landscape of connection options in Speckle. I have tried the built-in Speckle 2 Connector in Dynamo but with that approach i didn’t seem to get all data neccesairy. I’d like to get your opinion about this. Thanks again in advance! The help i get on this platform is great!
I’ll check with the team internally, but in my experience/view, updating objects with the same ID directly is possible, yet it is considered unSpeckle-like. That is not to say it is illegitimate, but it is not the direction of travel we have for our demonstration of Speckle.
That’s a lot of words to say; I disagree with what you found in our docs
The updating objects with the same ID isn’t something i read in the documents but just a usecase i’m working on at the moment (so no fault there on the Speckle-end ). The reason i’m interested in this idea is because of the following situation:
Lets say an architect models a certain wall in Archicad. After that, the structural engineer imports that wall into Revit and adjust some parameters and maybe also some of the geometry. When importing that same wall back into Speckle, it is no longer recognised as the same wall.
This situation affects the tracebillity of the object througout the design proces. What we are now trying to explore is if we can use Speckle in a way were we can still track the changes of certain objects over multiple transfers between different software. The goal here is that we can later use this data to optimize our designproces.
Maybe updating the object to the same id is not the right way, but thats the approach which came to mind with my (still limited) knowlegde of the Speckle ecosystem. Do you know if there are allready other functionalities available which we can use to track the changes of objects over multiple transfers through different software?
Ah, the ID problem. It is much debated. A universal UID for objects externalised to the database and the authoring application—now that’s Strange Matter territory.
But before diving into solutions, it’s worth asking: Why is tracking an object across tools and versions essential to your current challenges? Is this driven by:
Design Auditing: Accountability or version control needs?
Coordination: Streamlining collaboration between disciplines?
Optimisation: Understanding how changes cascade through the design.
Or is it a more theoretical exploration to future-proof your workflows? If theoretical, it’s worth examining whether it aligns with Speckle’s capabilities, as universal object tracking often introduces practical complexities. Speckle’s versioning and metadata features might already meet your needs more simply.
The Current Landscape of Object Identification in Speckle
By default, Speckle handles object identification in two ways:
applicationId: Assigned by the host application:
Revit might use a GUID tied to its database.
Archicad would have its logic.
Navisworks, with no permanent UID concept, maps applicationId to a hierarchical path index. This is inherently software-specific and breaks when the object moves between platforms or is multi-authored.
speckleId: A hash based on an object’s content (geometry, metadata, etc.), unique to its exact state at the creation time. Any modification—intentional or software-induced—generates a new ID.
Thus, neither applicationId (software-specific and mutable) nor speckleId (content-based and immutable) can reliably track objects across versions or tools.
Why Cross-Software Tracking Is Challenging
Content Dependency: Speckle IDs change with any alteration to geometry or metadata.
Application-Specific Logic: applicationIds are tied to the originating software, lost or altered when objects are transformed.
Multi-Author Workflows: Collaborative edits across tools lead to new applicationIds, further compounding the issue.
No Universal Standards: Traceability remains elusive without a shared global UID system across platforms.
Potential Workarounds
globalId or Custom Properties:
Use a shared ID manually or via middleware to persist object lineage across tools.
Speckle supports custom properties, but not all tools faithfully transmit metadata.
Metadata and Geometric Matching:
Compare secondary properties like dimensions, material, or geometry as a “fingerprint.” However, metadata loss or precision issues can limit reliability.
Middleware for Reconciliation:
Custom tools or scripts to map relationships between IDs (applicationId, globalId) and establish traceability.
Standardised Workflows:
Agree on conventions for object creation, modification, and sharing to maintain consistency.
Speckle Automate:
Develop automation scripts to compare objects, identify lineage, and track changes programmatically.
Speckle’s Role in This
Speckle is designed to share, version, and collaborate on data, but its IDs focus on immutable snapshots rather than evolving object tracking. Cross-software traceability requires leveraging custom workflows, metadata, or middleware. If this challenge is critical, we can explore tailored approaches to your needs.