Skip to main content

Using the SDK

Creating a client

DimeSchedulerClient is the single entry point. It needs an API key and, optionally, an environment:

from dimescheduler import DimeSchedulerClient, Environment

client = DimeSchedulerClient(api_key="MY_API_KEY") # production
client = DimeSchedulerClient(api_key="MY_API_KEY", environment=Environment.Sandbox)

The client owns an httpx.Client under the hood and should be closed when you're done. Use it as a context manager so the connection pool is released for you:

with DimeSchedulerClient(api_key="MY_API_KEY") as client:
client.categories.create({"name": "INSTALL", "displayName": "Install", "color": "#22d3ee"})

For long-lived processes (web apps, workers) instantiate the client once at startup and reuse it across requests.

Domain-grouped accessors

Every entity hangs off a typed accessor on the client. The naming mirrors the .NET and JavaScript SDKs 1:1, with idiomatic snake_case:

client.categories          # /category
client.appointments # /appointment
client.jobs # /job
client.tasks # /task
client.resources # /resource
client.filter_groups # /filterGroup
client.filter_values # /filterValue
client.messages # /message
client.notifications # /notification

CRUD-shaped entities (most of them) expose create / update / delete / get_all:

client.categories.create(category)
client.categories.update(category)
client.categories.delete(category)
client.categories.get_all()

Endpoints with their own shape get purpose-built methods:

client.appointments.get(start_date, end_date, resources=["R1", "R2"])
client.notifications.get(page=1, limit=50, sort="createdAt:desc")
client.geocoding.geocode_text("221B Baker Street", "GB")
client.optimization.field_service(request)
client.messages.send({"text": "Heads up!", "severity": "Warning"})

For the full list of accessors, see the API reference or the client source.

Results, not exceptions

Every call returns a Result:

result = client.categories.get_all()

result.ok # True on 2xx
result.data # parsed JSON body on success, else None
result.error # parsed JSON error body on 4xx/5xx, else None
result.response # underlying httpx.Response - headers, status code, raw bytes

The dispatcher never raises on non-2xx - you decide how to react. If you'd rather work with exceptions, call raise_for_error():

from dimescheduler import RateLimitError, ValidationError

result = client.categories.create(category)
try:
result.raise_for_error()
except RateLimitError as e:
time.sleep(e.retry_after or 1)
except ValidationError as e:
log.warning("bad payload: %s", e.body)

The typed exception hierarchy covers ValidationError (400/422), AuthenticationError (401), AuthorizationError (403), NotFoundError (404), ConflictError (409), RateLimitError (429), ServerError (5xx), and NetworkError (transport failures).

Retries

The SDK retries transient failures by default: connection errors, timeouts, and HTTP 408 / 429 / 500 / 502 / 503 / 504. Backoff is exponential with full jitter, capped at 30 seconds, and Retry-After is honoured.

Override the policy via RetryConfig:

from dimescheduler import DimeSchedulerClient, RetryConfig

client = DimeSchedulerClient(
api_key="MY_API_KEY",
retry=RetryConfig(max_retries=5, initial_delay_s=1.0, max_delay_s=60.0),
)

Disable retries entirely with retry=False.

Timeouts and cancellation

The client-level timeout (default 30 s) applies to every request. Override it for a single call:

client.imports.run(payload, timeout=120.0)         # 120 s
client.imports.run(payload, timeout=httpx.Timeout(60.0, connect=5.0))
client.imports.run(payload, timeout=None) # wait indefinitely

Omit timeout to inherit the client-level default.