Client#

The main entry point for interacting with the Ionworks API.

Main client module for the Ionworks API.

This module provides the Ionworks client, which is the main entry point for interacting with the Ionworks API. It handles authentication, request/response processing, and provides access to all API resources through sub-clients.

class ionworks.client.Ionworks(api_key=None, api_url=None, project_id=None, dataframe_backend=None, timeout=None, max_retries=None, token=None, organization_id=None)[source]#

Bases: object

Client for interacting with the Ionworks API.

Handles authentication, request/response processing, and provides access to all API resources through sub-clients.

Parameters:
  • api_key (str | None)

  • api_url (str | None)

  • project_id (str | None)

  • dataframe_backend (str | None)

  • timeout (int | None)

  • max_retries (int | None)

  • token (str | None)

  • organization_id (str | None)

__init__(api_key=None, api_url=None, project_id=None, dataframe_backend=None, timeout=None, max_retries=None, token=None, organization_id=None)[source]#

Initialize Ionworks client.

Authentication uses either a bearer token or an API key. If a token is provided (argument or IONWORKS_API_TOKEN env var) it is sent as an Authorization: Bearer header; otherwise an API key (argument or IONWORKS_API_KEY env var) is sent as an X-API-Key header. A token takes precedence when both are present.

Parameters:
  • api_key (str | None) – API key. If not provided, will look for IONWORKS_API_KEY env var.

  • api_url (str | None) – API URL. If not provided, will look for IONWORKS_API_URL env var.

  • project_id (str | None) – Default project ID to use for sub-client methods that take a project_id argument. If not provided, will look for the IONWORKS_PROJECT_ID env var (falling back to the deprecated PROJECT_ID env var with a DeprecationWarning). May be left unset; methods that need a project will raise a clear error if none is available.

  • dataframe_backend (str | None) – DataFrame backend for returned data: “polars” or “pandas”. If not provided, uses IONWORKS_DATAFRAME_BACKEND env var (defaults to “polars”).

  • timeout (int | None) – Request timeout in seconds. Defaults to 10 seconds if not provided.

  • max_retries (int | None) – Maximum number of retries for failed requests. Defaults to 5 if not provided. Retries occur on connection errors, timeouts, and 5xx server errors.

  • token (str | None) – Bearer token to authenticate with instead of an API key. Sent as an Authorization: Bearer header. Falls back to the IONWORKS_API_TOKEN env var, but only when neither token nor api_key is passed explicitly: an argument always outranks the environment, and a token outranks an API key only within the same source. So Ionworks(api_key=...) authenticates with that key even in a shell (or an agent tool subprocess) that exports IONWORKS_API_TOKEN.

  • organization_id (str | None) – Organization to scope every request to, sent as an X-Organization-Id header. Falls back to the IONWORKS_ORGANIZATION_ID env var. Relevant when the auth principal spans multiple organizations (a bearer token usually does); with an API key the organization is already fixed by the key and this can be left unset. When unset entirely, no header is sent and the backend resolves the organization from the credential.

Return type:

None

request(method, endpoint, json_payload=None)[source]#

Make a request to the Ionworks API with standardized error handling.

Requests use the configured timeout and will retry up to the configured maximum number of times on connection errors, timeouts, and 5xx server errors.

Parameters:
Return type:

Any

request_raw(method, endpoint, timeout=None)[source]#

Make a request and return raw response bytes.

Intended for endpoints that return binary data or redirect to storage. Uses the session (which follows redirects automatically), so auth headers are sent on the initial request and stripped on cross-origin redirects.

Parameters:
  • method (str) – HTTP method (e.g. “GET”).

  • endpoint (str) – API endpoint path (e.g. “/cell_measurements/{id}/time_series”).

  • timeout (tuple[int, int] | int | None, optional) – Request timeout. Defaults to (10, 300) – 10s connect, 300s read.

Returns:

Raw response body.

Return type:

bytes

get(endpoint)[source]#

Make a GET request using the request helper.

Parameters:

endpoint (str)

Return type:

Any

post(endpoint, json_payload)[source]#

Make a POST request using the request helper.

Parameters:
Return type:

Any

post_multipart(endpoint, files=None, params=None)[source]#

POST to endpoint with optional multipart files and query params.

When files is None or empty, the request is sent as a plain POST with only query-string params (no body, no multipart Content-Type).

Parameters:
  • endpoint (str) – API endpoint path.

  • files (dict[str, Any] or None, optional) – Files mapping in the form expected by requests (e.g. {"file": (filename, fileobj, content_type)}). Pass None for endpoints that take only query-string params.

  • params (dict[str, Any] | None, optional) – Query string parameters.

Returns:

Parsed JSON response body.

Return type:

Any

patch(endpoint, json_payload)[source]#

Make a PATCH request using the request helper.

Parameters:
Return type:

Any

delete(endpoint)[source]#

Make a DELETE request using the request helper.

Parameters:

endpoint (str)

Return type:

None

upload_multipart(endpoint, *, data=None, files=None, method='POST')[source]#

Send a multipart/form-data request.

Goes through the session (not bare requests.post) so the upload gets the retry-aware adapter. requests builds the Content-Type header (with the right boundary) only when none is supplied, so the session’s JSON Content-Type is dropped for this request via headers={"Content-Type": None}.

Parameters:
  • endpoint (str) – API endpoint path, e.g. "/models/upload-custom".

  • data (dict[str, Any] | None) – Form fields to send alongside the file(s).

  • files (dict[str, Any] | None) – requests-style files mapping (typically {"file": (filename, fileobj, content_type)}).

  • method (str, optional) – HTTP method to use. Defaults to "POST" for create-style endpoints; pass "PATCH" for endpoints that replace an existing resource’s file.

Returns:

Parsed JSON response, or the raw Response if the response body isn’t JSON.

Return type:

Any

health_check()[source]#

Check the health of the Ionworks API.

Returns:

Health check response.

Return type:

dict[str, Any]

whoami()[source]#

Return the user profile the configured API key resolves to.

Hits GET /users/me and is the recommended way to debug API-key issues: the authorized_organization field is the organization this request is authorized as — for SDK requests, that’s the org the configured API key was issued for, which is the source of truth for permission checks on every call the SDK makes. The organizations field is the user’s full membership list and is a different question.

Returns:

User profile payload. Notable keys:

  • id : user id

  • email : user email

  • authorized_organization : {"id": ..., "name": ...} or None — the org this request is authorized as. For SDK requests, the org the API key is scoped to.

  • organizations : list of every org the user belongs to.

Return type:

dict[str, Any]

Raises:

IonworksError – status_code=401 if the configured API key is missing, wrong, or expired.

Examples

>>> me = client.whoami()
>>> me["authorized_organization"]
{'id': '...', 'name': 'Acme Battery'}
resolve_measurement(cell_specification, cell_instance, measurement, *, project_id=None)[source]#

Resolve a measurement from human-readable names.

Walks the spec -> instance -> measurement hierarchy by name, filtering each level server-side via name_exact, and returns the resolved measurement. Saves callers from hand-walking the three list endpoints.

Parameters:
  • cell_specification (str) – Exact name of the cell specification.

  • cell_instance (str) – Exact name of the cell instance within that specification.

  • measurement (str) – Exact name of the measurement within that instance.

  • project_id (str | None, optional) – Project to resolve the specification within. Defaults to the client’s project. Spec names are unique per project, not per organization, so resolving without a project would report a name shared with a sibling project as ambiguous.

Returns:

The resolved measurement (use .id for the measurement id).

Return type:

CellMeasurement

Raises:
  • IonworksError – status_code=404 if any level has no match, or 409 if a name is ambiguous within its parent.

  • ValueError – If no project_id is given and the client has no default.

Examples

>>> m = client.resolve_measurement("Cell A spec", "Cell A #1", "RPT 0")
>>> m.id
'...'
capabilities()[source]#

Fetch platform capabilities and domain context.

Returns domain knowledge (battery data hierarchy, key concepts), authentication info, and pointers to JSON Schema endpoints.

Returns:

Capabilities including domain_context, schemas, openapi_spec, and authentication.

Return type:

dict[str, Any]

schema(name)[source]#

Fetch a discovery schema by name.

Parameters:

name (str) –

Schema to fetch. Supported values:

  • "data" — cell data hierarchy (specifications, instances, measurements, steps, time_series).

  • "protocol" — Universal Cycler Protocol (UCP) JSON Schema.

Returns:

The requested schema.

Return type:

dict[str, Any]

Raises:

ValueError – If name is not a recognised schema.

pybamm_models()[source]#

List pybamm/ionworks model classes and option values.

Use this to decide whether you can express your model as a config (client.model.create({"config": {"pybamm_model": ..., "options": {...}}})) or whether you need client.model.upload_custom for a custom pybamm.BaseModel subclass.

Returns:

{"pybamm_models": {<module>: [<class names>]}, "ionworks_models": {...}, "options": {<name>: [<allowed values>]}, "pybamm_version": "..."}.

Return type:

dict[str, Any]

validate_pybamm_model_config(pybamm_model, options=None, module='lithium_ion')[source]#

Check whether a (model, options) combination is buildable.

Tries to instantiate the model server-side via the same code path the simulation pipeline uses. Returns {"valid": True} on success, or {"valid": False, "error": <message>, "error_type": <exception class>} if pybamm/ionworks rejects the combination. Nothing is persisted.

Parameters:
  • pybamm_model (str) – Class name (e.g. "DFN", "SPM", "ECM"). One of the names listed by pybamm_models().

  • options (dict[str, Any] | None, optional) – Options dict passed to the model constructor.

  • module (str, optional) – PyBaMM submodule ("lithium_ion" or "lead_acid"). Ignored for ionworks-specific models. Defaults to "lithium_ion".

Returns:

Validation result.

Return type:

dict[str, Any]