Skip to main content
This is 2026.9 documentation. Coverage here is incremental: a page exists only where 2026.9 differs or is newly documented. For any other topic, switch to Current (2026.8 and earlier) in the version selector.
If you load versions without a Speckle SDK, there is no root object to download and no graph to walk. You list the version’s artifacts, fetch the parquet files you need from presigned URLs, and rebuild the model from three key spaces joined by relations. A loader that downloads referencedObject from the objects endpoints gets a 404 on every 2026.9 version. This page assumes the model from Building integrations in 2026.9.

Tell the two formats apart

Any version you are asked to load may still be an object graph from 2026.8 or earlier. Read the version record first. Dispatch on the bundle. prefix. Keep your existing reader for the first shape, or refuse it with a clear message the way the Archicad connector does. Never derive storage paths from the triple in the reference; resolve the version through the project and version ids you already hold.

How a load fetches a version

1

Resolve the version

Take the version id from the model URL, or list the model’s versions and take the latest. The outcome is a project, model, and version id, and a version record whose schemaVersion is 3.
2

List the artifacts

Get the version’s artifacts endpoint with your Speckle token. The outcome is one entry per file with a presigned URL and an expiry, and the version’s viewer .dat in the list.
3

Download the files you need

Get each URL without your Speckle token. Skip the geometry shards when you only read properties, and skip the .dat. The outcome is a bundle directory on local disk.
4

Read the catalogs first

Open meta, rel_types, and node_kinds. The outcome is the vocabulary this bundle was written with, including relation namespaces and any ids your reader does not know.
5

Rebuild the model

Intern objects, nodes, and geometry by their dense keys, then apply relations in the order the rules below give. The outcome is objects with properties, geometry, placement, grouping, and appearance.
6

Mark the version received

Call the mark-received mutation with your application slug. The outcome is a receive recorded against the version, the way every Speckle connector does.
The SDK tabs run the whole sequence in one call. The GraphQL and REST tabs are the calls a non-SDK consumer makes, numbered to match the steps.
Variables for MarkReceived
Presigned URLs expire after an hour and are not content-addressed. Never persist one. Cache the downloaded files by version id and revalidate with the ETag when you refetch.
The .dat in the listing is the viewer’s artifact, and a geometryStream field beside the file list is the viewer’s streaming endpoint. Both are internal. Read the parquet files.

Rules that decide whether your load is correct

The bundle tells you its own vocabulary. Read it, and apply these rules in order.

Reading the files

  • Read columns by name and tolerate columns you do not know. The spec adds columns without moving the version, so a bundle written before a column existed must still load.
  • Read every geometry shard, {id}.geometries.parquet and {id}.geometries.{n}.parquet. A reader that opens only shard zero silently drops geometry above the shard cap.
  • Treat a relation id or node kind missing from your vocabulary as skip-and-report, never as an error. A newer producer than your reader is normal.
  • Do not gate on meta.schema_version. It is provenance, not a compatibility switch.

Identity

  • A bare integer is meaningless without its namespace. The relation type’s source and target namespaces in rel_types say whether an end is an object, a node, or a geometry.
  • The object’s identity is applicationId. If you project the bundle into a tree with ids on nodes, mint synthetic ids per bundle and expect them to differ across versions.

Properties

  • Each row sets exactly one of the string, number, and boolean columns. Coalesce them.
  • Rebuild nesting from the dotted path. properties.Constraints.Base Offset is a nested dictionary, not a flat key.
  • Merge type-level rows into each object through the object-to-type link. Without that merge, most type parameters are missing.
  • The root scalars speckle_type, name, units, and type sit beside properties.*, not under it.

Geometry

  • Verify the CRC and decode by primitive type. See Geometry encoding in 2026.9.
  • DISPLAY is what to render. Prefer a SOLID only when your host can read its format, and fall back to the display mesh otherwise. Never draw CENTERLINE as a body.
  • Convert with the blob’s own unit, not a model-wide unit. Objects, instances, and geometry can disagree.

Instancing

  • Expand a definition once through DEFINES, then place it for every DISPLAY_INSTANCE edge using the instance node’s transform, 16 row-major doubles in the instance’s units. Scale only the translation when you convert units. DEFINES_INSTANCE nests one definition in another.
  • An object with no render edge is a carrier for a definition member’s properties and grouping. Skip it when you bake geometry, or the member draws twice, once untransformed at the origin. DEFINES_MEMBER and PLACES join carriers to their definition and placement.

Grouping

  • Build the tree from the default scene view. Each tier is either a relation such as IN_MODEL or IN_COLLECTION, or a property path such as category. With no scene view, group by IN_COLLECTION.
  • Nest containers through their parent reference column, not through a relation.
  • IN_COLLECTION is single-valued. IN_GROUP and IN_SYSTEM are not.

Appearance

  • Material fills from specific to general: HAS_MATERIAL on the geometry, then OBJECT_HAS_MATERIAL on the object, then NODE_HAS_MATERIAL on the object’s container.
  • Color is presentational: OBJECT_HAS_COLOR overrides HAS_COLOR on the geometry, and NODE_HAS_COLOR is the container default.
  • HAS_COLOR starts from a geometry or an object, and ord says which. Read it before you resolve the source key.
  • Appearance edges are single-valued per source. When a bundle repeats one, the last row wins.

Placement

  • Read modelPlacement.* and referencePoint.* from the model-scoped properties. When appliedToGeometry is true, stored coordinates are already in that datum. When it is false, apply the transform yourself. No rows means the internal origin.

Suggested build order

1

List and download

Authenticate, resolve a version, list its artifacts, and download the non-geometry files. The outcome is a bundle directory and a passing read of the three catalogs.
2

Read properties only

Objects by applicationId, nested properties from paths, type-level rows merged in. The outcome is a property table you can filter, before any geometry.
3

Decode display meshes

Download the shards, verify CRCs, decode meshes, attach them through DISPLAY with the right units. The outcome is a model that renders untransformed geometry correctly.
4

Expand instances

Definitions, placements, nested definitions, and carrier suppression. The outcome is repeated objects in the right places, each drawn once.
5

Apply grouping and appearance

The default scene view, container nesting, and the material and color precedence. The outcome is a tree and a look that match the Speckle viewer.
6

Apply placement and mark received

The reference point contract, then the mark-received call. The outcome is geometry in the right datum and a receive recorded on the version.

FAQ

Either the version is an object graph from 2026.8 or earlier, the bundle has not been produced yet, or your token cannot read the project. Check schemaVersion on the version record first, then the ingestion status if the version is new.
Yes. Geometry is the bulk of a bundle and lives in its own shards. Download the eav and envelope files only. The SDKs expose the same choice as an include-geometry option.
Only as a new version, and every publish is one. Files are stored under the reserved version id, so the server never sees “the same bundle”. Your choice is how to make the new file set. Copying the received files, rewriting the property rows you changed, stamping meta with your own producer, renaming to the new id, and uploading is valid when only values change: keys, relations, and geometry stay consistent. Build a new bundle when structure changes. Either way the version’s source application is you. Speckle’s own parameter editing applies changes in the host and republishes from there, and a receive-then-send round trip through a Base tree is unsupported.
No, but every Speckle connector does. It is how the web app and analytics know a version was loaded, and it costs one mutation.
Skip its edges and report which ids you skipped. The SDKs surface the same set as unknown relations. Do not fail the load and do not guess a meaning from the number.
Last modified on September 16, 2026