Skip to content

mapi_client

This page shows the Python client for the /v1 HTTP API. For tested procedures, read the Python client guide. For a summary of each resource, read CLI and Python client. The text on this page comes from the docstrings. AsyncClient has the same resources, but you use await with them.

Clients

Python client for the modeling-api /v1 HTTP API.

  • :class:Client / :class:AsyncClient - typed with the mapi_spec.api DTOs; resources projects, catalog, datasets, specs, runs, models and plots, and from v0.3 tenants, tokens, usage and admin (plus :meth:Client.me);
  • credentials: an API token (MAPI_TOKEN, config profile) or the OIDC sign-in stored by mapi login (:mod:mapi_client.oidc), renewed automatically;
  • project selection: Client(project="acme/growth") / MAPI_PROJECT / the profile's project is sent as X-Mapi-Project on project-scoped requests;
  • 429 handling: RATE_LIMITED is waited out (Retry-After) and resent; QUOTA_EXCEEDED raises :class:~mapi_spec.errors.QuotaExceeded with :func:retry_after_of (see :class:RetryPolicy);
  • errors are :class:mapi_spec.errors.MapiError subclasses rebuilt from RFC 7807 problems (see :mod:mapi_client.errors);
  • list endpoints return lazy :class:Paginator / :class:AsyncPaginator iterators;
  • runs.stream_events follows the SSE stream and resumes with Last-Event-ID;
  • datasets.upload and models.score handle signed URLs, waiting and CRC32C checks; xr.Dataset uploads and xr.DataTree results need the xarray extra;
  • from v0.4 guided, endpoints (and Client.endpoint(alias), a :class:RemoteEndpoint whose score(ds) returns an xr.Dataset), webhooks, saved plots, renders and embeds on plots, sign-up (:meth:Client.signup) and the trust lifecycle on tenants/admin; :mod:mapi_client.webhooks verifies deliveries and :mod:mapi_client.xrjson encodes inline payloads;
  • from v0.5 workflows (documents, revisions, runs with :meth:stream_events - an SSE iterator of :class:WorkflowSnapshot, :class:WorkflowEventFrame and :class:WorkflowEnd - node outputs, schedules, triggers, the template gallery), governance (check catalog, project and tenant policies), validations (requests, the review queue, approvals, evidence packs), explorations and the Data/Model Explorer, comparison and budget optimisation (models.optimize) methods, and About cards with Help me choose on catalog (abouts, chooser, recommend);
  • from v0.11 run tracking on runs: update (name, note, tags), log_metric(s), log_params, set_tags, metrics, metric_history, params, run search in list (filters, order_by, columns, tags) and :meth:Runs.track, a buffered :class:RunTracker; stream_events yields :class:RunTrackingFrame;
  • from v0.14 run media on runs (media, media_keys, get_media, download_media - size, CRC32C and sha256 checked - log_image, log_table), runs.compare and runs.keys, list(experiment_id=...), and the resources experiments (named groups of runs) and run_views (saved runs-table searches).

from mapi_client import Client # doctest: +SKIP with Client("http://127.0.0.1:8000") as api: ... version = api.datasets.upload("eu_media.zarr.zip", dataset="eu_media_daily")

Client

Client(
    base_url: str | None = None,
    *,
    token: str | None = None,
    project: str | None = None,
    config: ClientConfig | None = None,
    auth: Auth | None = None,
    transport: BaseTransport | None = None,
    storage_transport: BaseTransport | None = None,
    retry: RetryPolicy | None = None,
    sleep: Callable[[float], None] = sleep,
)

Synchronous client for the /v1 API.

with Client() as api: # doctest: +SKIP ... run = api.runs.create({"kind": "fit", "spec_id": sid, "revision": 1}) ... run = api.runs.wait(run.id)

Settings come from :func:~mapi_client.config.load_config unless config is given (arguments, MAPI_URL/MAPI_TOKEN/MAPI_PROJECT, ~/.config/mapi/config.toml, defaults). Credentials: the configured token, else the sign-in mapi login stored for the profile (see :func:~mapi_client.auth.default_auth). project (<tenant>/<project>) is sent as X-Mapi-Project on project-scoped requests.

project

project: str | None

The X-Mapi-Project selector of project-scoped requests.

use

use(project: str | None) -> None

Select the project for subsequent requests (<tenant>/<project>).

scope_headers

scope_headers() -> dict[str, str]

X-Mapi-Project for a project-scoped request (empty without a selection).

me

me() -> Me

GET /v1/me: who you are and where you may act (v0.3).

endpoint

endpoint(alias: str) -> RemoteEndpoint

An endpoint of the selected project as an object (.schema(), .validate(ds), .score(ds) -> xr.Dataset).

signup

signup(
    email: str,
    name: str,
    *,
    accepted_terms: bool,
    organisation: str | None = None,
    terms_version: str | None = None,
    challenge: str | None = None,
) -> SignupAccepted

POST /auth/signup (public; the answer is the same for known addresses). The e-mail carries a link with the token for :meth:verify_email.

verify_email

verify_email(token: str) -> VerificationResult

POST /auth/verify-email: creates a public-tier tenant and its project.

health

health() -> Health

GET /healthz (process liveness).

ready

ready() -> Health

GET /readyz (status is fail/degraded when a dependency is down).

send

send(call: Call[T]) -> T

Send one described request; see :class:RetryPolicy for what is resent.

put_signed

put_signed(
    session: UploadSession, src: UploadSource
) -> None

PUT src to an upload session's signed URL (CRC32C-checked).

download

download(link: ArtifactLink, dest: None = None) -> bytes
download(
    link: ArtifactLink, dest: str | PathLike[str]
) -> Path
download(
    link: ArtifactLink,
    dest: str | PathLike[str] | None = None,
) -> bytes | Path

Fetch a signed artifact link; verify size and CRC32C.

Returns the bytes, or the path when dest is given (written atomically).

AsyncClient

AsyncClient(
    base_url: str | None = None,
    *,
    token: str | None = None,
    project: str | None = None,
    config: ClientConfig | None = None,
    auth: Auth | None = None,
    transport: AsyncBaseTransport | None = None,
    storage_transport: AsyncBaseTransport | None = None,
    retry: RetryPolicy | None = None,
    sleep: Callable[[float], Awaitable[None]] = sleep,
)

Asynchronous client for the /v1 API (use async with).

Configuration, credentials and project selection work as for :class:~mapi_client.Client. A stored mapi login sign-in is renewed synchronously inside the request (a brief blocking call to the identity provider).

project

project: str | None

The X-Mapi-Project selector of project-scoped requests.

use

use(project: str | None) -> None

Select the project for subsequent requests (<tenant>/<project>).

scope_headers

scope_headers() -> dict[str, str]

X-Mapi-Project for a project-scoped request (empty without a selection).

me

me() -> Me

GET /v1/me: who you are and where you may act (v0.3).

endpoint

endpoint(alias: str) -> AsyncRemoteEndpoint

An endpoint of the selected project as an object (see Client.endpoint).

signup

signup(
    email: str,
    name: str,
    *,
    accepted_terms: bool,
    organisation: str | None = None,
    terms_version: str | None = None,
    challenge: str | None = None,
) -> SignupAccepted

POST /auth/signup (public; the same answer for known addresses).

verify_email

verify_email(token: str) -> VerificationResult

POST /auth/verify-email: creates a public-tier tenant and its project.

send

send(call: Call[T]) -> T

Send one described request; see :class:RetryPolicy for what is resent.

ClientConfig

ClientConfig(
    base_url: str = DEFAULT_URL,
    token: str | None = None,
    timeout: float = DEFAULT_TIMEOUT,
    max_retries: int = DEFAULT_MAX_RETRIES,
    verify: bool = True,
    profile: str | None = None,
    allow_insecure_token: bool = False,
    project: str | None = None,
    oidc_issuer: str | None = None,
    oidc_discovery_url: str | None = None,
    oidc_client_id: str | None = None,
    oidc_client_secret: str | None = None,
    credentials_file: Path | None = None,
    sources: Mapping[str, str] = dict(),
)

Resolved connection settings. Secrets (token, oidc_client_secret) are hidden from repr.

project

project: str | None = None

X-Mapi-Project sent on project-scoped requests (<tenant>/<project>).

oidc_discovery_url

oidc_discovery_url: str | None = None

Where the issuer's discovery document lives when it is not under the issuer (the dev profile's built-in IdP serves it at <api>/dev/idp); its issuer must still equal :attr:oidc_issuer.

credentials_file

credentials_file: Path | None = None

Where mapi login keeps interactive sign-ins. None (the default for configs built in code) never reads stored credentials; :func:load_config sets it.

sources

sources: Mapping[str, str] = field(
    default_factory=dict, compare=False
)

Where each setting came from (arg, env:MAPI_URL, file:<profile>, default).

profile_key

profile_key: str

The name stored sign-ins are kept under (default without a profile).

insecure_transport

insecure_transport: bool

Plain http to a non-loopback host: no credential may be sent there.

with_overrides

with_overrides(**changes: Any) -> ClientConfig

A copy with some fields replaced (validation runs again).

RetryPolicy

RetryPolicy(
    max_retries: int = 2,
    base_delay: float = 0.5,
    max_delay: float = 30.0,
    rate_limit_retries: int = 4,
    max_rate_limit_wait: float = 120.0,
    max_quota_wait: float = 0.0,
    jitter: float = 0.1,
)

When and how long to wait before resending a request.

  • Transport errors and 502/503/504: idempotent calls only (safe methods, Idempotency-Key, or by definition), max_retries times, exponential backoff with full jitter, honouring Retry-After (capped at max_delay).
  • 429 RATE_LIMITED: the server refused the request before acting on it (:mod:mapi_spec.quotas runs before any handler), so every method is resent, up to rate_limit_retries times, after max(Retry-After, base·2^n) plus a little jitter. A Retry-After longer than max_rate_limit_wait is not waited out: the error is raised with :func:~mapi_client.errors.retry_after_of set.
  • 429 QUOTA_EXCEEDED: raised at once, unless the quota resets within max_quota_wait seconds (default 0: never wait for a quota window).
  • A bare 429 without a problem document (a proxy) is treated like RATE_LIMITED for idempotent calls only.

jitter

jitter: float = 0.1

Fraction of a throttle delay added as random jitter (at most one second).

delay

delay(
    attempt: int, response: Response | None = None
) -> float

Backoff before retry attempt (0-based) of a transport or gateway failure.

should_retry

should_retry(
    call: Call[Any], attempt: int, response: Response | None
) -> bool

Retry a transport error (response=None) or a 429/502/503/504 answer?

plan

plan(
    call: Call[Any],
    state: RetryState,
    response: Response | None,
) -> float | None

Seconds to wait before resending call, or None to give up.

response is None after a transport error. state is updated.

load_config

load_config(
    *,
    url: str | None = None,
    token: str | None = None,
    profile: str | None = None,
    timeout: float | None = None,
    max_retries: int | None = None,
    path: Path | None = None,
    environ: Mapping[str, str] | None = None,
    allow_insecure_token: bool = False,
    project: str | None = None,
    oidc_issuer: str | None = None,
    oidc_client_id: str | None = None,
    oidc_discovery_url: str | None = None,
) -> ClientConfig

Resolve a :class:ClientConfig from arguments, environment, config file and defaults.

Workflows (v0.5)

Synchronous M3.5 resources (workflows, governance, explorers, optimisation, About cards; v0.5).

Client.workflows, Client.governance, Client.validations, Client.explorations, the About/chooser/node/check methods of Client.catalog, the About and Data Explorer methods of Client.datasets and the explorer, comparison, optimisation and validation methods of Client.models.

Workflows

Workflows(client: Client)

Bases: _Resource

Workflows (Client.workflows, v0.5): documents and revisions, runs with live node status, node outputs, schedules, dataset triggers and the template gallery.

find

find(name: str) -> Workflow | None

The workflow called name in the project (archived ones included).

create

create(
    source: WorkflowSource | None = None,
    *,
    template: str | None = None,
    message: str | None = None,
) -> Workflow

Create a workflow from a document (a WorkflowSpec, a mapping, YAML text or a file path) or from a gallery template (copied into the project as revision 1). A document with errors is stored but cannot run until a revision fixes it.

validate

validate(source: WorkflowSource) -> WorkflowValidation

Static checks on the server (stores nothing): valid, issues with JSON pointers, the execution order and the resolved node implementations.

update

update(
    workflow_id: str,
    *,
    description: str | None = None,
    archived: bool | None = None,
) -> Workflow

Change the description, or archive/unarchive (documents change by revisions).

delete

delete(workflow_id: str) -> None

Delete the workflow with its runs, schedules and triggers.

revise

revise(
    workflow_id: str,
    source: WorkflowSource,
    *,
    message: str | None = None,
    expected_revision: int | None = None,
) -> WorkflowRevision

Save a new revision (validated; expected_revision refuses a concurrent edit with 409). Check revision.validation.valid before running it.

upsert

upsert(
    source: WorkflowSource, *, message: str | None = None
) -> tuple[Workflow, WorkflowRevision]

Create the workflow, or add a revision when its document changed (matched by metadata.name). Returns the workflow and its latest revision.

run

run(
    workflow_id: str,
    *,
    inputs: Mapping[str, str] | None = None,
    params: Mapping[str, JsonValue] | None = None,
    revision: int | None = None,
    use_cache: bool = True,
    resource_class: ResourceClass | str | None = None,
    experiment_id: str | None = None,
    idempotency_key: str | None = None,
    wait: bool = False,
    timeout: float | None = None,
    poll_interval: float = 2.0,
    raise_on_failure: bool = True,
) -> WorkflowRun

Start a run (inputs are references such as dataset://growth/sales@latest, pinned to an exact version at start). experiment_id puts the run and every run it starts in that experiment (v0.14). With wait the run is followed until it is terminal and a failed or cancelled run raises its error.

get_run

get_run(run_id: str) -> WorkflowRun

A run with every node (status, result, outputs), decisions, outputs and cost.

wait

wait(
    run_id: str,
    *,
    timeout: float | None = None,
    poll_interval: float = 2.0,
    raise_on_failure: bool = True,
) -> WorkflowRun

Poll until the run is terminal (TimeoutError after timeout seconds).

cancel

cancel(run_id: str) -> WorkflowRun

Cancel the run and its running children (cancelling until they stopped).

stream_events

stream_events(
    run_id: str,
    *,
    last_event_id: int | None = None,
    reconnect: bool = True,
    max_reconnects: int = 5,
) -> Iterator[WorkflowStreamItem]

Follow the run's server-sent events until it ends.

Yields :class:~mapi_client.sse.WorkflowSnapshot (first frame of each connection: the run with every node), :class:~mapi_client.sse.WorkflowEventFrame (node queued/started/succeeded/cached/skipped/failed, branch decided, ...) and finally :class:~mapi_client.sse.WorkflowEnd. A dropped connection is resumed with Last-Event-ID; events are never yielded twice.

events

events(
    run_id: str,
    *,
    after: int | None = None,
    limit: int | None = None,
) -> Paginator[WorkflowEvent]

The persisted events as JSON pages (ascending seq, after after).

node

node(run_id: str, node_id: str) -> NodeRun

One node's status, resolved parameters, result, outputs and child runs.

output_link(
    run_id: str, node_id: str, port: str
) -> ArtifactLink

A signed link to a node output's file (a derived dataset, a fitted bundle). JSON outputs (test results, tables, metrics) are inline in :meth:node.

download_output

download_output(
    run_id: str, node_id: str, port: str, dest: None = None
) -> bytes
download_output(
    run_id: str,
    node_id: str,
    port: str,
    dest: str | PathLike[str],
) -> Path
download_output(
    run_id: str,
    node_id: str,
    port: str,
    dest: str | PathLike[str] | None = None,
) -> bytes | Path

Download a node output's file (CRC32C-verified): bytes, or the path.

schedule

schedule(
    workflow_id: str,
    cron: str,
    *,
    timezone: str = "UTC",
    inputs: Mapping[str, str] | None = None,
    params: Mapping[str, JsonValue] | None = None,
    revision: int | None = None,
    active: bool = True,
    description: str | None = None,
) -> WorkflowSchedule

Run the workflow on a cron schedule ("0 6 * * 1": Mondays at 06:00) in timezone; at most every 15 minutes.

update_schedule

update_schedule(
    workflow_id: str,
    schedule_id: str,
    *,
    cron: str | None = None,
    timezone: str | None = None,
    revision: int | None = None,
    params: Mapping[str, JsonValue] | None = None,
    inputs: Mapping[str, str] | None = None,
    active: bool | None = None,
    description: str | None = None,
) -> WorkflowSchedule

Change a schedule; active=False pauses it.

trigger

trigger(
    workflow_id: str,
    dataset: str,
    input: str,
    *,
    revision: int | None = None,
    params: Mapping[str, JsonValue] | None = None,
    active: bool = True,
    debounce_seconds: int | None = None,
) -> WorkflowTrigger

Run the workflow whenever dataset (dataset://project/name) gets a new version, bound to the workflow input input.

templates

templates(
    *, limit: int | None = None
) -> Paginator[WorkflowTemplate]

The gallery: each template with its About card and document.

Workflow run events (v0.5)

Server-sent events: a WHATWG-conformant line decoder and typed run-stream items.

GET /v1/runs/{run_id}/events (Accept: text/event-stream) sends snapshot (the full :class:~mapi_spec.api.Run, no id) first on every connection, then the persisted run events (id: = :attr:RunEventView.id) after Last-Event-ID, then live events, and finally end (the final run) before closing. : keepalive comments are heartbeats. progress and log frames are live and unpersisted: they carry no id: and are never replayed after a reconnect (:class:RunLiveFrame). tracking frames (v0.11, no id) tell which metric series changed and whether params or tags changed (:class:RunTrackingFrame).

GET /v1/workflow-runs/{run_id}/events follows the same pattern for workflow runs (v0.5): snapshot (the :class:~mapi_spec.workflow.WorkflowRun with every node), one frame per :class:~mapi_spec.workflow.WorkflowEvent (event: is its type, id: its seq) and end (the run id and its final status), decoded by :func:to_workflow_stream_item.

WorkflowSnapshot

WorkflowSnapshot(run: WorkflowRun)

First frame of every connection: the workflow run as it is now, with every node.

WorkflowEventFrame

WorkflowEventFrame(event: WorkflowEvent)

One persisted workflow event (a node started, succeeded, was cached or skipped, a branch was decided, ...); :attr:id is its seq (the Last-Event-ID cursor).

WorkflowEnd

WorkflowEnd(run_id: str, status: WorkflowRunStatus | None)

The workflow run is terminal; the server closes the stream after this frame.

to_workflow_stream_item

to_workflow_stream_item(
    frame: SseEvent,
) -> WorkflowStreamItem | None

Decode a frame of the workflow run event stream (unknown event names are skipped).

Governance and validations (v0.5)

Synchronous M3.5 resources (workflows, governance, explorers, optimisation, About cards; v0.5).

Client.workflows, Client.governance, Client.validations, Client.explorations, the About/chooser/node/check methods of Client.catalog, the About and Data Explorer methods of Client.datasets and the explorer, comparison, optimisation and validation methods of Client.models.

Governance

Governance(client: Client)

Bases: _Resource

Governance policies (Client.governance, v0.5): the check catalog and versioned project and tenant-wide policies. tenant_id= addresses the tenant's policies.

policies

policies(
    *,
    scope: PolicyScope | None = None,
    tenant_id: str | None = None,
    limit: int | None = None,
) -> Paginator[GovernancePolicy]

Policies in force in the project (tenant-wide first), or a tenant's own.

policy

policy(
    policy_id: str, *, tenant_id: str | None = None
) -> GovernancePolicy

The latest version of a policy.

create_policy

create_policy(
    policy: GovernancePolicyCreate
    | Mapping[str, Any]
    | None = None,
    *,
    tenant_id: str | None = None,
    name: str | None = None,
    checks: Sequence[PolicyCheck | Mapping[str, Any] | str]
    | None = None,
    applies_to: PolicyMatch
    | Mapping[str, Any]
    | None = None,
    **fields: Any,
) -> GovernancePolicy

Add a policy (version 1). checks may be check ids with the catalog defaults, or :class:~mapi_spec.governance.PolicyCheck mappings with severity, thresholds and params; other fields: description, require_approval, approvals_required, require_validated_for_promotion, active.

update_policy

update_policy(
    policy_id: str,
    policy: GovernancePolicyCreate
    | GovernancePolicy
    | Mapping[str, Any]
    | None = None,
    *,
    tenant_id: str | None = None,
    expected_version: int | None = None,
    **fields: Any,
) -> GovernancePolicy

Save the next version (the whole policy - a fetched one, edited, may be sent back as it is; expected_version refuses a concurrent edit with 409).

retire_policy

retire_policy(
    policy_id: str, *, tenant_id: str | None = None
) -> None

Retire a policy (its versions stay for audit).

policy_versions

policy_versions(
    policy_id: str, *, limit: int | None = None
) -> Paginator[GovernancePolicy]

Every version of a project policy, newest first.

Validations

Validations(client: Client)

Bases: _Resource

Model validations (Client.validations, v0.5): requests, the reviewers' queue, evidence, second-person approvals and the evidence pack.

request

request(
    model_id: str,
    version: int,
    *,
    policy_ids: Sequence[str] = (),
    note: str | None = None,
    dataset: str | None = None,
    wait: bool = False,
    timeout: float | None = 1800.0,
    poll_interval: float = 2.0,
    idempotency_key: str | None = None,
) -> ModelValidation

Submit a model version: the policies in force (or policy_ids) decide the checks, which run in the sandbox. With wait it returns once the checks finished (validated, awaiting_approval, checks_failed, ...).

list

list(
    *,
    status: ValidationStatus | str | None = None,
    limit: int | None = None,
) -> Paginator[ModelValidation]

Validations of the project; status="awaiting_approval" is the review queue.

wait

wait(
    validation_id: str,
    *,
    timeout: float | None = 1800.0,
    poll_interval: float = 2.0,
) -> ModelValidation

Poll until the checks finished (the status no longer changes by itself).

evidence

evidence(
    validation_id: str, *, limit: int | None = None
) -> Paginator[CheckResult]

Every check result with its evidence.

cancel

cancel(
    validation_id: str, *, note: str | None = None
) -> ModelValidation

Stop running checks (back to draft).

resubmit

resubmit(
    validation_id: str,
    *,
    note: str | None = None,
    idempotency_key: str | None = None,
) -> ModelValidation

Run the checks again after a failure or a rejection.

decide

decide(
    validation_id: str,
    decision: Literal["approve", "reject"],
    *,
    comment: str | None = None,
) -> ModelValidation

A reviewer's decision (signed-in reviewers only: never the submitter, never an API token). A rejection needs a comment.

deprecate

deprecate(
    validation_id: str, reason: str
) -> ModelValidation

Retire a validated model version (audited with the reason).

evidence_pack

evidence_pack(
    validation_id: str,
    *,
    format: Literal["html", "json"] = "json",
    include_plots: bool = True,
) -> EvidencePack

The audit export: the validation, every result with evidence, approvals, history, policies, lineage and a digest; format="html" adds a signed link to a static HTML rendering (download).

download_evidence_pack

download_evidence_pack(
    validation_id: str,
    dest: str | PathLike[str],
    *,
    include_plots: bool = True,
) -> Path

Write the evidence pack to dest: the HTML rendering for a .html path, else the JSON document.

About cards, explorers and optimisation (v0.5)

Synchronous M3.5 resources (workflows, governance, explorers, optimisation, About cards; v0.5).

Client.workflows, Client.governance, Client.validations, Client.explorations, the About/chooser/node/check methods of Client.catalog, the About and Data Explorer methods of Client.datasets and the explorer, comparison, optimisation and validation methods of Client.models.

CatalogAboutMixin

CatalogAboutMixin(client: Client)

Bases: _Resource

About cards, "Help me choose", workflow nodes and governance checks on Client.catalog (v0.5).

abouts

abouts(
    *,
    kind: AboutKind | str | None = None,
    limit: int | None = None,
) -> Paginator[CatalogAbout]

The About card of every item a user can pick (kind: model, step, split, template, workflow_template, node_kind, node, check).

about

about(
    item_id: str, *, kind: AboutKind | str | None = None
) -> About

One item's About card (ValueError when no installed item has that id).

chooser

chooser() -> ChooserQuestionnaire

The "Help me choose" questions, in the order to ask them.

recommend

recommend(
    answers: Mapping[str, Answer] | None = None,
    /,
    *,
    kind: AboutKind | str | None = None,
    limit: int | None = None,
    **more: Answer,
) -> ChooserResult

Catalog items ranked for chooser answers, best first, with plain reasons.

api.catalog.recommend(goal="forecast", data_shape="one_series", experience="beginner"); a question with several answers takes a list. Without kind the candidates are models, guided templates and workflow templates. Unknown questions or answers raise ValueError before anything is sent.

workflow_nodes

workflow_nodes(
    *,
    kind: NodeKind | str | None = None,
    limit: int | None = None,
) -> Paginator[NodeImplementation]

Workflow node implementations (ports, parameters, result fields, About).

governance_checks

governance_checks(
    *, limit: int | None = None
) -> Paginator[GovernanceCheckDef]

The governance check catalog (metric, thresholds, parameters, About).

DatasetAboutMixin

DatasetAboutMixin(client: Client)

Bases: _ExploreWaiting

Dataset About and the Data Explorer on Client.datasets (v0.5).

about

about(dataset_id: str) -> DatasetAbout

The owner's description and the summary generated from the latest version.

describe

describe(
    dataset_id: str, description: str | None
) -> DatasetAbout

Set (or, with None, clear) the owner's description of a dataset.

explore

explore(
    dataset_id: str,
    version: int,
    request: DataExploreRequest
    | Mapping[str, Any]
    | None = None,
    *,
    wait: bool = True,
    timeout: float | None = 900.0,
    poll_interval: float = 1.0,
    raise_on_failure: bool = True,
    idempotency_key: str | None = None,
    **fields: Any,
) -> Exploration

Compute Data Explorer sections in the sandbox (sections=[...], kpi=, facet_by=[...], max_lag=...). Asking the same again is instant (cached). With wait the run is followed until its views are ready; read them with :meth:Explorations.view.

ModelInsightMixin

ModelInsightMixin(client: Client)

Bases: _ExploreWaiting

The Model Explorer, comparisons, budget optimisation and validations on Client.models (v0.5).

explore

explore(
    model_id: str,
    version: int,
    request: ModelExploreRequest
    | Mapping[str, Any]
    | None = None,
    *,
    wait: bool = True,
    timeout: float | None = 900.0,
    poll_interval: float = 1.0,
    raise_on_failure: bool = True,
    idempotency_key: str | None = None,
    **fields: Any,
) -> Exploration

Compute Model Explorer sections (sections=[...], horizon=, compare_with=[model://...], backtest=<split plan>).

compare

compare(
    models: Sequence[str] | None = None,
    request: ModelCompareRequest
    | Mapping[str, Any]
    | None = None,
    *,
    wait: bool = True,
    timeout: float | None = 900.0,
    poll_interval: float = 1.0,
    raise_on_failure: bool = True,
    idempotency_key: str | None = None,
    **fields: Any,
) -> Exploration

Compare 2-11 model versions (model://project/name@vN) side by side: a metrics table, a ranking and pairwise Diebold-Mariano tests on the shared holdout (the comparison view).

optimize

optimize(
    model_id: str,
    version: int,
    request: OptimizeRequest
    | Mapping[str, Any]
    | None = None,
    *,
    wait: int = MAX_PREFER_WAIT_SECONDS,
    timeout: float | None = 900.0,
    poll_interval: float = 1.0,
    raise_on_failure: bool = True,
    idempotency_key: str | None = None,
    **fields: Any,
) -> Optimization

Split a budget across channels with mmm-framework's planner and wait for the plan (total_budget=, channels={"tv": {"max_multiplier": 1.5}}, objective="p10", frontier={"n_points": 12}...). Prefer: wait is sent and the request repeated with the same Idempotency-Key until it is done.

optimization

optimization(run_id: str) -> Optimization

An optimize run and, once done, its plan.

validate

validate(
    model_id: str,
    version: int,
    *,
    policy_ids: Sequence[str] = (),
    note: str | None = None,
    dataset: str | None = None,
    wait: bool = False,
    timeout: float | None = 1800.0,
    poll_interval: float = 2.0,
    idempotency_key: str | None = None,
) -> ModelValidation

Submit a model version for validation (see :meth:Validations.request).

validations

validations(
    model_id: str, version: int, *, limit: int | None = None
) -> Paginator[ModelValidation]

Validations of one model version, newest first.

Explorations

Explorations(client: Client)

Bases: _Resource

Explore runs (Client.explorations, v0.5): status, waiting and the views.

link(
    exploration: Exploration, section: str
) -> ArtifactLink

The signed link of one section's view (ValueError says why one is missing).

view

view(
    exploration: Exploration, section: str
) -> dict[str, Any]

One section's view as JSON (CRC32C-verified download): e.g. stationarity - ADF/KPSS per series - or comparison - the metrics table and Diebold-Mariano tests. Plot the views with the platform's Vega-Lite recipes (mapi_plots.explorer).

Endpoints (v0.4)

Synchronous M3 resources (guided mode and integrations, v0.4).

Client.guided, Client.endpoints, Client.webhooks, the saved-plot, render and embed methods of Client.plots, the trust lifecycle on Client.tenants and Client.admin, and :class:RemoteEndpoint (Client.endpoint(alias)).

Endpoints

Endpoints(client: Client)

Bases: _Resource

Endpoints and aliases (v0.4): promotion through the scorecard gate, history, rollback, schema, validation, scoring and snippets.

promote

promote(
    alias: str,
    model: str | None = None,
    *,
    model_version_id: str | None = None,
    override: bool = False,
    reason: str | None = None,
    expected_revision: int | None = None,
    evaluation_policy: EvaluationPolicy
    | Mapping[str, Any]
    | None = None,
    description: str | None = None,
) -> Endpoint

Create the alias or point it at another version (model://p/name@vN or model_version_id). Gated on the scorecard: 409 OVERRIDE_REQUIRED needs override=True with a reason from a signed-in project admin; PROMOTION_BLOCKED cannot be overridden. expected_revision=0: must be new.

delete

delete(alias: str) -> None

Delete the alias (the model versions stay).

history

history(
    alias: str, *, limit: int | None = None
) -> Paginator[EndpointRevision]

Promotions and rollbacks, newest first.

rollback

rollback(
    alias: str,
    reason: str,
    *,
    to_revision: int | None = None,
) -> Endpoint

Point the alias back at an earlier revision's version (default: the previous).

schema

schema(alias: str) -> EndpointSchema

What to send: the input schema frozen at promotion and an example payload.

validate

validate(
    alias: str,
    call: EndpointScoreCall
    | Mapping[str, Any]
    | None = None,
    **fields: Any,
) -> EndpointValidation

Static checks of a score call without running it (valid/issues).

submit

submit(
    alias: str,
    call: EndpointScoreCall
    | Mapping[str, Any]
    | None = None,
    *,
    wait: int | None = None,
    idempotency_key: str | None = None,
    **fields: Any,
) -> ScoreCallResult

One POST …/score (200 done or 202 running): no waiting loop.

score

score(
    alias: str,
    call: EndpointScoreCall
    | Mapping[str, Any]
    | None = None,
    *,
    wait: int = MAX_PREFER_WAIT_SECONDS,
    timeout: float | None = None,
    idempotency_key: str | None = None,
    download: bool = True,
    raise_on_failure: bool = True,
    poll_interval: float = 1.0,
    **fields: Any,
) -> ScoreResult

Score the endpoint's current version and wait for the result.

call is an :class:EndpointScoreCall (or mapping, e.g. the example of :meth:schema); keyword fields override it (mode=, horizon=, data=xr.Dataset - sent inline as XrJSON). Prefer: wait=<wait> is sent and the call is repeated with the same Idempotency-Key until the run is done or timeout passes. With the xarray extra and download=True the result DataTree is fetched (CRC32C-verified) into :attr:ScoreResult.tree.

forecast

forecast(
    alias: str,
    rows: Table | None = None,
    *,
    actuals: Table | None = None,
    future: Table | Sequence[Any] | int | None = None,
    periods: int | None = None,
    future_covariates: str = "carry_last",
    output: Mapping[str, Any] | None = None,
    schema: EndpointSchema | None = None,
    **options: Any,
) -> ScoreResult

Forecast with your latest actuals and the dates to forecast (the model is not refitted: it updates its state with the actuals and forecasts from the last one).

rows is a long table in the endpoint's input layout (schema.input_table: the time column, the target, the drivers) - a DataFrame or a list of row mappings: rows whose target holds a value are actuals, rows after them with it empty are forecast. Or split it: actuals= (rows with the target) and future= (the dates, rows with driver values, or a number of periods to append). Empty driver values on the future rows follow future_covariates (carried forward by default). Models that cannot use actuals refuse them (ActualsNotSupported) rather than ignore them.

The result's :attr:ScoreResult.conditioning says what the forecast was conditioned on. options are those of :meth:score (wait, timeout, download...).

snippets

snippets(
    alias: str,
    languages: Sequence[SnippetLanguage | str]
    | None = None,
    *,
    base_url: str | None = None,
) -> SnippetSet

Ready-to-run code (Python, TypeScript, curl, R, Apps Script, notebook).

RemoteEndpoint

RemoteEndpoint(client: Client, alias: str)

One endpoint as an object: Client().endpoint("geo-mmm-prod").score(ds).

score sends an xr.Dataset (or an XrJSON mapping, or a dataset:// reference) and returns the scored xr.Dataset of one result group (summary by default; draws when output={"draws": n} is requested). Needs the xarray extra.

info

info() -> Endpoint

The endpoint and the version it serves now.

schema

schema() -> EndpointSchema

What to send (fetched afresh; also kept to conform later payloads).

validate

validate(
    data: Payload | None = None,
    *,
    conform: bool = True,
    **fields: Any,
) -> EndpointValidation

Static checks of scoring data (and any call fields) without running it.

score_result

score_result(
    data: Payload | None = None, **options: Any
) -> ScoreResult

:meth:Endpoints.score for this endpoint (the run, links and tree).

forecast

forecast(
    rows: Table | None = None, **options: Any
) -> ScoreResult

:meth:Endpoints.forecast for this endpoint: actuals and the dates to forecast as a long table (actuals=, future=, periods=...); the schema is fetched once. result.conditioning.message says what the forecast used.

score

score(
    data: Payload | None = None,
    *,
    group: str = "summary",
    wait: int = MAX_PREFER_WAIT_SECONDS,
    timeout: float | None = None,
    conform: bool = True,
    **fields: Any,
) -> Dataset

Score data and return one group of the result as an xr.Dataset.

fields are :class:EndpointScoreCall fields (mode, horizon, scenario, output, interventions, ...). group picks the result group: summary (a stat dim: mean, hdi_90_lower, ...), draws (a sample dim), delta/summary for counterfactuals. With conform (default) a dataset's variables are transposed to the endpoint's input dim order first (the schema is fetched once).