Skip to main content
Versions published before 2026.9 stay readable. New and updated scripts use the 2026.9 Speckle.Sdk and Receive3: versions published by a 2026.9 connector need that build, and their full data shape only comes through Receive3. Speckle does not guarantee that older Speckle.Sdk builds, or Receive2, keep working against current servers. This page shows each change side by side so you can judge how much of your script moves. The old path is PAT → bootstrap → Receive2 → Flatten. The 2026.9 path is PAT → bootstrap → Receive3, which returns a disposable Model with columnar properties and typed relations. For the data model itself, see Object model. For dates and who must act, see Data model migration for developers.
An older Speckle.Sdk gets a 404 when it loads a version published by a 2026.9 connector. Update the package before you change any code. See Who’s affected.

What changes for a script

Update packages

Update every Speckle NuGet reference to the same 2026.9 version, then remove Speckle.Objects. 2026.9.0-beta.7 is the current 2026.9 build on NuGet; a plain dotnet add package Speckle.Sdk still installs 2026.8, which has no Receive3. A later stable 2026.9.0 replaces the beta pin; the calls on this page do not change.
The command writes this reference into your project file:
Then delete the Speckle.Objects package reference. Namespaces stay Speckle.Objects.*, so your using lines do not change.
A pre-2026.9 Speckle.Objects next to a 2026.9 Speckle.Sdk fails the build. Update every Speckle package together.
The bootstrap does not change. typeof(Speckle.Objects.Geometry.Point).Assembly in AddSpeckleSdk still compiles, because geometry types now live in the Speckle.Sdk assembly. You only need to pass an assembly when you register your own Base types.

Load a model

Receive2 is marked [Obsolete] in 2026.9. Receive3 takes the same account and ids and returns a disposable Model. Wrap that Model in using: it owns the downloaded bundle files on disk until you dispose it. Auth, bootstrap, and version lookup stay as on Automate with scripts. The snippets below assume account, client, projectId, modelId, and latest are already in scope.
Prior to 2026.9
Receive3 also takes the model URL the web app copies: Receive3(account, new Uri(modelUrl), options: null, cancellationToken: default). Leave out @versionId to load the latest version.
Receive3 reads the version’s bundle. A version published before 2026.9 that the server has not converted has no bundle, and Receive3 throws a SpeckleException. Load that version with Receive2.

Count and filter objects

Before 2026.9 you walk a Base tree. In 2026.9, objects are a flat list. Properties are path-keyed ("category", "Constraints.Base Offset"). Relations are accessors, not proxy lists.
Prior to 2026.9
Look up one object with model.ObjectByApplicationId(id). ApplicationId is the only identity a bundle object has. Do not treat Base.id as a content hash on a 2026.9 version.

Replace property walks

Before 2026.9, nested parameters are dictionaries you walk: obj.properties["x"] then ["y"]. In 2026.9 those paths are flat, and PropertyView replaces the walk. PropertyView (Speckle.Sdk.Pipelines.Receive.Artifacts) is a read-only view over one object’s property rows. Keys are dotted paths ("Constraints.Base Offset"), not nested dictionaries. It does not allocate until you enumerate it. ModelObject.Properties is this view; cast to PropertyView when you need the helpers below.
  • GetString / GetDouble / GetBool: typed lookup. Null if the path is missing or the value is another type.
  • Under("Constraints"): the subtree under that prefix, with the prefix stripped. No allocation.
  • Indexer / TryGetValue: untyped lookup, same paths as GetString.
  • ToNested(): the old nested-dictionary tree. Allocates. Use it only when a caller still needs that shape.
ModelObject.GetString, GetDouble, and GetBool look up instance properties first, then type properties, then root scalars. Prefer those for a single path. Use PropertyView.Under when you need a group.
Prior to 2026.9

Replace proxy walks

Before 2026.9, grouping by level or material meant indexing applicationIds and resolving proxy objects lists. In 2026.9, use the typed relation accessors directly. See Relations for the names.
2026.9
A 2026.9 version has no nested elements tree and no proxy objects lists. Do not unpack proxies to rebuild containment; read the relation accessors instead.

Read versions published before 2026.9

Receive2 is obsolete. Keep it only to read versions published before 2026.9 that have no bundle; use Receive3 for everything else.
  • Versions published before 2026.9: pass referencedObject as a content hash and get the object graph back.
  • Versions published in 2026.9: referencedObject is a bundle reference (bundle.<projectId>.<modelId>.<versionId>). A 2026.9 SDK recognizes the prefix and returns a best-effort Base tree (DataObject idiom, version = 4 on the root). That projection does not scale to the model sizes the bundle format is built for, and it is not a lossless round trip. Do not build new work on it.
  • Older SDKs: fetching a bundle reference from the objects API returns 404 with upgrade guidance. Update Speckle.Sdk rather than parsing the 404 body.
Transport-based Receive cannot load 2026.9 versions. It throws if you pass a bundle reference.
Receiving a 2026.9 version as a Base tree and sending it again with Send2 is not a supported copy workflow. The tree is a baked view, not the authored graph.
Receive, derive new data, then send to a new version remains supported.

Publish from a script

Most analysis scripts only receive. If your script calls Send2 then Version.Create, move it to Send3 with a BundleBuilder. Send2 is obsolete, and Speckle does not guarantee it for new work; see Publish through model ingestions. Send3 returns a SendResult with a reserved version id as soon as the upload finishes. The version appears in queries and at its URL, and fires webhooks, when the server finishes processing. Call WaitForVersion when the same script needs the version to exist.
2026.9

FAQ

No, not any longer. Update Speckle.Sdk to 2026.9.0-beta.7 and load versions with Receive3. Older Speckle.Sdk builds get a 404 on versions from a 2026.9 connector, and Speckle does not guarantee they keep working against current servers. Keep Receive2 only to read versions published before 2026.9 that have no bundle.
Model is the bundle itself: objects, path-keyed properties, and relation accessors, with geometry parsed only when you ask. A Base tree inflates every object and mesh into managed objects, which is why Receive2 is obsolete for the new format.
The downloaded parquet files stay in a scratch directory until Dispose runs. Always wrap the result in using. Objects and geometry you already read stay in memory after dispose; geometry you have not touched cannot be read afterwards.
Only to read versions published before 2026.9. Transports never carry bundles, so load everything else with Receive3. See Load and publish model data.
Last modified on October 19, 2026