Skip to main content
Use IOperations to load model data from Speckle Server (Receive2), publish results back (Send2), or serialize graphs locally. For most AEC scripts, Receive2/Send2 is the recommended path — see Load and publish model data before reading signatures here. Guides: Build your first model analysis tool · Send analysis results back
https://mintcdn.com/speckle/VtRPWzmN-ULoLfIv/images/developers/sdks/csharp.svg?fit=max&auto=format&n=VtRPWzmN-ULoLfIv&q=85&s=f2970e3b8bd4a2c7899b46211a42f251Example
var operations = provider.GetRequiredService<IOperations>();

Serialize / Deserialize

Serialize
string Serialize(Base value, CancellationToken cancellationToken = default)
Serializes an object graph to a JSON string with no transport involved. No detachment occurs beyond what’s declared via [DetachProperty]/@ prefixes; nested objects are still inlined unless detached.
DeserializeAsync
Task<Base> DeserializeAsync(string value, CancellationToken cancellationToken = default)
Reconstructs a Base graph from a JSON string previously produced by Serialize.

Send / Receive

Send
Task<(string rootObjId, IReadOnlyDictionary<string, ObjectReference> convertedReferences)> Send(Base value, IReadOnlyCollection<ITransport> transports, IProgress<ProgressArgs>? onProgressAction = null, CancellationToken cancellationToken = default)
Sends value to every transport in transports. Returns the root object’s id and a map of converted references.Overloads accept a single IServerTransport/ITransport plus a useDefaultCache flag, which adds a matching local SQLiteTransport/SQLiteTransport2 automatically.
Receive
Task<Base> Receive(string objectId, ITransport? remoteTransport = null, ITransport? localTransport = null, IProgress<ProgressArgs>? onProgressAction = null, CancellationToken cancellationToken = default)
Receives the object graph identified by objectId. Checks localTransport first (defaults to a new SQLiteTransport if omitted); falls back to remoteTransport and copies the result into the local transport.
https://mintcdn.com/speckle/VtRPWzmN-ULoLfIv/images/developers/sdks/csharp.svg?fit=max&auto=format&n=VtRPWzmN-ULoLfIv&q=85&s=f2970e3b8bd4a2c7899b46211a42f251Example
using var transport = provider.GetRequiredService<IServerTransportFactory>().Create(client.Account, project.id);

var (objectId, _) = await operations.Send(myData, transport, useDefaultCache: true);
var received = await operations.Receive(objectId, remoteTransport: transport);
ServerTransport has DI-resolved constructor dependencies. Always construct it via IServerTransportFactory.Create(account, projectId), not new ServerTransport(...).

Send2 / Receive2

Send2
Task<SerializeProcessResults> Send2(Uri url, string streamId, string? authorizationToken, Base value, IProgress<ProgressArgs>? onProgressAction, CancellationToken cancellationToken, SerializeProcessOptions? options = null)
Sends value directly to the server at url for project streamId (the project id), using the newer V2 serialization pipeline. Recommended over Send for new server-facing work.
Receive2
Task<Base> Receive2(Uri url, string streamId, string objectId, string? authorizationToken, IProgress<ProgressArgs>? onProgressAction, CancellationToken cancellationToken, DeserializeProcessOptions? options = null)
Receives an object graph directly from the server, using the V2 deserialization pipeline.
https://mintcdn.com/speckle/VtRPWzmN-ULoLfIv/images/developers/sdks/csharp.svg?fit=max&auto=format&n=VtRPWzmN-ULoLfIv&q=85&s=f2970e3b8bd4a2c7899b46211a42f251Example
var results = await operations.Send2(client.ServerUrl, project.id, account.token, myData, null, cancellationToken: default);
var received = await operations.Receive2(client.ServerUrl, project.id, results.RootId, account.token, null, cancellationToken: default);
The streamId parameter name is a legacy holdover — pass your project id.

SerializeNew

SerializeNew
string SerializeNew(Base value)
An experimental System.Text.Json-based serializer, not yet the default. Avoid for production workflows — see Load and publish model data.

SendPipeline

Connector-scale ingestion is a separate factory-created pipeline, not a method on IOperations. See Publish large models (connectors) for the full workflow.
https://mintcdn.com/speckle/VtRPWzmN-ULoLfIv/images/developers/sdks/csharp.svg?fit=max&auto=format&n=VtRPWzmN-ULoLfIv&q=85&s=f2970e3b8bd4a2c7899b46211a42f251Example
var pipeline = provider.GetRequiredService<ISendPipelineFactory>()
    .CreateInstance(ingestion, account, uploadProgress: new Progress<StreamProgressArgs>(), cancellationToken: default);
var reference = await pipeline.Process(myData);
await pipeline.WaitForUpload();
After WaitForUpload, the server processes the uploaded pack and creates the version asynchronously — the caller does not call client.Version.Create on this pathway. See Publish large models (connectors).
uploadProgress must be IProgress<StreamProgressArgs> — pass new Progress<StreamProgressArgs>() if you don’t need to report progress.

Exceptions

ExceptionThrown when
ArgumentExceptionNo transports specified, or an invalid argument
ArgumentNullExceptionvalue or transport was null
SpeckleExceptionSerialization or send/receive operation failed
TransportExceptionOne or more transports failed to send
SpeckleDeserializeExceptionDeserialization of the requested object(s) failed
OperationCanceledExceptionThe cancellation token requested cancellation
See Exceptions for the full hierarchy.

FAQ

Use Send2/Receive2 — see Automate with scripts. Use Send/Receive when you follow the Full send/receive tour, need MemoryTransport/SQLiteTransport, or integrate with existing transport-based code.
No for Send and Send2 — call client.Version.Create after send. SendPipeline creates the version on the server after upload — see Publish large models (connectors) and VersionResource.
When uploading a whole host-application model from a connector — thousands of elements converted incrementally. See Publish large models (connectors).

Next Steps

Load and publish model data

Choose Receive2, Send2, or SendPipeline

Build your first model analysis tool

Receive2 worked example

Version

Publish after Send2
Last modified on July 10, 2026