Skip to main content

Using the SDK

This page walks you through the everyday workflow with the .NET SDK: create a client, call typed accessors against the Dime.Scheduler REST API, read results, and tune retries and cancellation.

Creating a client​

DimeSchedulerClient is the single entry point. It needs an API keyAPI keyA credential that authenticates calls to the Dime.Scheduler API. The preferred way to integrate over the deprecated JWT flow. and optionally an environment:

using Dime.Scheduler;
using Dime.Scheduler.Entities;

// Production (default)
var production = new DimeSchedulerClient("MY_API_KEY");

// Sandbox
var sandbox = new DimeSchedulerClient("MY_API_KEY", Dime.Scheduler.Environment.Sandbox);

// Custom retry policy
var tuned = new DimeSchedulerClient("MY_API_KEY", Dime.Scheduler.Environment.Sandbox, RetryOptions.Default);

Environment has two members, Production and Sandbox. Because System.Environment is almost always in scope as well, qualify it as Dime.Scheduler.Environment - the SDK's own examples do the same.

DimeSchedulerClient is thread-safe and meant to be long-lived - instantiate it once at startup (e.g. as a singleton in your DI container) and reuse it.

Domain accessors​

Every entity hangs off a typed accessor on the client. The accessor list mirrors the JS and Python SDKs 1:1 - same names, idiomatic casing per language:

// CRUD: CreateAsync, UpdateAsync, DeleteAsync, GetAllAsync<TDto>()
client.Categories // /category
client.Resources // /resource
client.FilterGroups // /filterGroup
client.FilterValues // /filterValue
client.Tags // /tag
client.ProjectMembers // /projectMember
client.TaskDependencies // /taskDependency

// CRUD plus a purpose-built read
client.Appointments // /appointment GetAsync(start, end, resources), GetByIdAsync(id)
client.Jobs // /job GetAsync(jobNo)
client.Tasks // /task GetAsync(isOpen, page, pageSize)
client.Notifications // /notification GetAsync(page, limit, sort, group, filter)
client.TimeEntries // /timeEntry GetAsync(start, end)
client.TimeSessions // /timeSession GetAsync(start, end)

// Create and delete only
client.TaskAssignments // /taskAssignment
client.TaskBudgetEntries // /taskBudgetEntry

// Read-only: GetAllAsync()
client.Calendars // /calendar
client.ResourceTypes // /resourcetype
client.AppointmentFields // /appointmentField
client.AppointmentDependencies // /appointmentDependency

// Purpose-built
client.Messages // /message
client.Geocoding // /geocode
client.Optimization // /optimization
client.Recommendation // /recommendation
client.Imports // /import
client.Users // /user
client.Connectors // /connector
client.RecurringAppointments // /appointmentRecurring

CRUD-shaped entities expose CreateAsync, UpdateAsync, DeleteAsync, and GetAllAsync<TDto>(). All write methods accept either a single entity or an IEnumerable<T>:

await client.Categories.CreateAsync(new Category { Name = "VIP", Color = "#22d3ee" });
await client.Categories.CreateAsync(new[] { cat1, cat2, cat3 });
await client.Categories.UpdateAsync(category);
await client.Categories.DeleteAsync(category);

Result<ICollection<CategoryDto>> categories = await client.Categories.GetAllAsync<CategoryDto>();

Endpoints with their own shape get purpose-built methods:

await client.Appointments.GetAsync(startDate, endDate, new[] { "R1", "R2" });
await client.Jobs.GetAsync("SO001");
await client.Notifications.GetAsync(page: 1, limit: 50, sort: "createdAt:desc");
await client.Messages.SendAsync(new Message { Text = "Heads up!", Severity = Severity.Warning });
await client.Geocoding.GeocodeAsync(address);
await client.Optimization.OptimizeFieldServiceAsync(request);

For the full accessor list, see DimeSchedulerClient.cs.

Results​

Every call returns a Result. CRUD writes return Result<DimeSchedulerApiResponse> and reads return Result<T> with the requested DTO:

var result = await client.Categories.CreateAsync(category);

result.IsSuccess // bool
result.IsFailure // !IsSuccess
result.Value // the payload on success
result.Error // typed Error on failure

Several specialized calls - messages, connectors, imports, optimization, recommendation, users, task assignments, and recurring appointments - return a non-generic Result with no Value; there you only check IsSuccess and Error.

The SDK never throws on a non-2xx - you decide how to react. Error comes as a subclass per status (ValidationError, NotFoundError, RateLimitError, ServerError, ...), and on a 429 the RateLimitError.RetryAfter property echoes the server's Retry-After header when present. A typical guard:

var result = await client.Categories.CreateAsync(category);
if (result.IsFailure)
{
logger.LogWarning("Create failed: {Error}", result.Error);
return;
}

Retries​

Transient failures retry by default - connection errors, timeouts, and HTTP 408 / 429 / 500 / 502 / 503 / 504. Backoff is exponential with jitter and honors Retry-After.

Override the policy with RetryOptions. Its properties are init-only, so set them in an object initializer:

var client = new DimeSchedulerClient(
"MY_API_KEY",
Dime.Scheduler.Environment.Production,
new RetryOptions { MaxRetries = 5, InitialDelay = TimeSpan.FromSeconds(1) });

The other knobs are MaxDelay (cap on a single backoff, default 30 seconds), BackoffMultiplier (default 2), RetryStatusCodes (the status codes listed above), and RespectRetryAfter (default true). Pass RetryOptions.Disabled to turn retries off entirely; it is the same as MaxRetries = 0.

Cancellation​

Every async method accepts a CancellationToken as the last argument:

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var result = await client.Categories.GetAllAsync<CategoryDto>(cts.Token);

The SDK sets no per-request timeout of its own, so the HttpClient default of 100 seconds applies. Use a token when you need a tighter deadline or want to abort an in-flight call from the outside (a user closing a UI, a long-running batch job hitting a deadline).