Architecture Overview
The SDK is organized around a core HTTP client layer, endpoint wrappers that model the iMednet API, workflow helpers that combine multiple endpoint calls, and a CLI built on top of those pieces.
Components
Core Client
The synchronous Client implements authentication,
retry handling, and JSON serialization for each API request. It inherits from
HTTPClientBase and is shared by all endpoint classes. HTTP transport is
handled by httpx.
HTTP Transport Contract
The transport layer in imednet.core.http provides the following guarantees:
Retry policy
Retries are evaluated by
imednet.core.retry.DefaultRetryPolicy.Idempotent methods (
GET,PUT,DELETE,HEAD,OPTIONS) retry on:httpx.RequestErrornetwork failuresHTTP
5xxresponses
All methods (including
POST/PATCH) retry on HTTP429rate limits.Non-idempotent methods do not retry on network errors or
5xxresponses.Maximum attempts are controlled by the
retriesargument onClient,AsyncClient,ImednetSDK, andAsyncImednetSDK.Backoff uses Tenacity’s randomized exponential wait strategy with
backoff_factoras the multiplier.If a retriable response includes
Retry-After, that delay overrides the backoff schedule.
Timeouts
timeoutis forwarded directly intohttpx.Client/httpx.AsyncClient.You can pass either a float (single timeout applied to all phases) or
httpx.Timeoutfor per-phase timeouts.
Status-code error mapping
Response errors are mapped via imednet.errors.get_error_class():
Status code |
Raised exception |
|---|---|
400 |
|
401 |
|
403 |
|
404 |
|
409 |
|
429 |
|
500-599 |
|
other |
Credential redaction
Transport logs never include raw credential headers.
URLs logged by request monitoring are sanitized through
imednet.utils.url.redact_url_query(), redacting sensitive query params such asapi_key,security_key,token,secret, andpassword.Retry exhaustion raises
imednet.errors.RequestErrorwith a generic message that does not expose credentials.
Async Client
AsyncClient provides the same features as the
sync client but leverages async/await for concurrency. The public SDK
surface is split into two client classes:
ImednetSDKfor synchronous usage only.AsyncImednetSDKfor asynchronous usage only.
Migration note: if you previously used async behavior from ImednetSDK, move
to AsyncImednetSDK and manage lifecycle with
async with or await sdk.aclose().
Endpoints
Each endpoint, such as StudiesEndpoint,
wraps a related set of API operations. Endpoints now use composition:
GenericListGetEndpoint composes operation classes (for example
ListOperation and FilterGetOperation) rather than inheriting deep
operation mixin chains. This keeps method resolution straightforward, improves
IDE autocomplete, and avoids MRO-related typing ambiguity. Endpoints can cache
responses when called without filters and expose list/get methods that
return typed models.
Workflows
Workflows orchestrate several endpoints to perform higher level tasks. For
example, RecordUpdateWorkflow validates
record payloads, submits them, and polls resulting jobs. Workflows have sync and
async variants and are available under sdk.workflows.
Caching
Caching Behavior describes how endpoint and schema data are cached. Cached values
can be refreshed by passing refresh=True to endpoint methods or calling
schema.refresh() on a validator.
CLI
The Command Line Interface (CLI) uses Typer to expose common workflows on the command line. Each
command creates an ImednetSDK instance, invokes a workflow,
and closes the SDK when finished.
Data Flow
Extension Points
Adding New Endpoints
Subclass
GenericEndpointorGenericListGetEndpoint.Register the class in
_ENDPOINT_REGISTRYwithinimednet.sdksoImednetSDKexposes it.Document the endpoint in
docs/endpoints/and add tests.
Adding New Workflows
Create a workflow under
imednet/workflowsand provide sync and async methods where appropriate.Instantiate the workflow in
Workflowsinsideimednet.sdk.Add CLI commands or examples that demonstrate the workflow.
Update documentation and tests.
Export Sink Architecture
The SDK supports four distinct export paths. Choose the right path based on the shape of data you want to land at the destination.
Export Path Decision Matrix
Path |
When to use |
Key components |
|---|---|---|
Tabular |
Destination is a flat/columnar store (CSV, Excel, SQL, DuckDB, Parquet). All variables for a form can be represented as columns. |
|
Document |
Destination is a document store (for example MongoDB) and should keep
nested |
|
Graph |
Destination models relationships natively (for example Neo4j) and the hierarchy Study → Subject → Visit → Record should be preserved. |
|
Warehouse |
Destination is a cloud data warehouse with a native bulk loader. Records are staged as Parquet files and then COPY’d in a single command for best throughput. |
|
Data flow diagram
Error propagation
Transient errors are retried up to
max_retriestimes with exponential back-off.After all retries are exhausted, sinks raise
ExportBatchError(carriesbatch_id) so that callers can log and resume partial exports.Misconfiguration (missing credentials, invalid URIs) raises
ExportConfigurationErrorimmediately before any data is written.Credentials and connection URIs are never written to logs. Pass URIs through
_redact_uri()before logging them.
Optional dependency conventions
Each sink module calls
_require_optional_dep() at
connection time (not at import time). This means:
import imednet.integrations.graphnever raises even whenneo4jis not installed.The error is raised when the first sink instance is created.
The error message tells the user which
imednet[<extra>]to install.
Extras naming:
pip install 'imednet[neo4j]' # Neo4j driver
pip install 'imednet[mongodb]' # PyMongo client
pip install 'imednet[snowflake]' # Snowflake connector + pyarrow
pip install 'imednet[export]' # Tabular path (pandas, SQL, Parquet, DuckDB)
Public API exposure
imednet.integrationsre-exports all tabular helpers and all three new sink classes (backward-compatible).Graph/document/warehouse sinks can also be imported directly from their submodules:
apache_airflow_providers_imednet.exportwraps only the tabular helpers. Airflow DAGs that need graph or warehouse sinks should import them directly fromimednet.integrations.
Adding New Export Sinks
Create a module under
packages/core/src/imednet/integrations/.Subclass
ExportSinkand implementwrite_batch,flush, andclose.Call
_require_optional_dep()inside the constructor (not at module level).Add the optional dependency to
packages/core/pyproject.tomland define a new[tool.poetry.extras]key.Re-export the new class from
imednet.integrations.Add unit tests; run
pytest --cov=imednet.integrations.