The command line v0.2¶
mapi (package mapi-cli, Apache-2.0) works in two locations:
- Locally, without a server. You scaffold a spec, check it, fit it and score it in your
own Python process, with the installed plugins (
new,check,fit,score,catalog,plugin,spec). - Remotely, against the HTTP API of a platform that runs. You upload
datasets, fit, follow runs and score model versions (
datasets,runs, and--remoteoncheck,fit,scoreandcatalog).
The generated CLI reference lists all commands and
options. The examples on this page are scripts that the test suite runs. The default suite
runs the local scripts. make e2e runs the remote scripts.
Running the commands
make install puts mapi into the workspace environment. You can activate the
environment (source .venv/bin/activate). Alternatively, you can put uv run before
each command (uv run mapi --help).
Without a server¶
Scaffold a spec from a template. --with-data also writes the sample data of the
conformance fixture that matches. This option needs the mapi-conformance package. The
workspace has this package.
| Template | What it is | Conformance fixture |
|---|---|---|
geo-mmm |
Hierarchical geo MMM (weekly EUR, adstock, saturation) | E33 |
forecast |
HSGP trend and seasonality forecast | C08 |
tabular |
XGBoost demand with quantile uncertainty | xgb_store_demand |
glm |
Hierarchical GLM, long layout | E02 |
Check the spec statically against the installed plugins and the schema of the data.
--stages shows the schema after each pipeline step. If there are errors, the exit status
is 1. Thus the command works in CI:
Fit in-process. The bundle goes to bundles/<name>/. It contains the zarr zip,
sidecars, plots, metrics and the evaluation bundle of evaluate_then_refit.
--side-table NAME=PATH supplies side tables:
mapi score request.yaml --bundle bundles/<name> --data future.zarr.zip -o result.zarr.zip
scores a local bundle with a ScoreRequest document.
Local means trusted
Local fit and score import and run the plugins in your own process (isolation
NONE), exactly as a notebook does. Use them only with code and data that you trust. On
the platform, the same work runs in a sandbox.
Inspect the catalog of installed plugins. Upgrade spec documents across
apiVersions:
mapi catalog models
mapi --json catalog steps | jq -r '.steps[].id' | head -n 5
mapi spec upgrade spec.yaml --check # exit 0: already the current apiVersion
mapi plugin init NAME scaffolds a plugin package (model, entry point, contract-kit tests).
mapi plugin test NAME runs its tests. See Write a plugin.
With a server¶
First, start the stack (make dev, then make seed). See the
quickstart.
Select the API¶
Each remote command finds the API in the same way as the Python client. The first match in this list wins:
--urland--token. These are global options. Put them before the command:mapi --url http://… runs ls.MAPI_URL,MAPI_TOKENandMAPI_PROFILE. IfMAPI_URLis not set, the CLI usesMAPI_API_URL, the name thatmake devuses.- The selected profile in
~/.config/mapi/config.toml. If$MAPI_CONFIGor$XDG_CONFIG_HOME/mapi/config.tomlis set, the CLI uses that file. http://127.0.0.1:8000.
# ~/.config/mapi/config.toml
profile = "local"
[profiles.local]
url = "http://127.0.0.1:8000"
[profiles.other-ports]
url = "http://127.0.0.1:18000"
timeout = 60
mapi config show shows the resolved URL, profile, project and credentials. It also shows
the source of each value. It never shows a token. An API token shows as mapi_<prefix>_…. A
sign-in shows as the person who signed in and the time when the sign-in ends.
mapi config path shows the location of the file.
mapi config set KEY VALUE and mapi config unset KEY change the selected profile. The
selected profile is --profile. If you do not give it, it is MAPI_PROFILE, and then the
default of the file. These commands write the file again with mode 0600. They do not keep
comments. You cannot set secrets in this way. Use mapi login --with-token.
--remote @ on check, fit, score and catalog means "the configured API".
--remote URL overrides it for one command.
Tokens
v0.2 is single-tenant and has no authentication. The API listens only on 127.0.0.1.
When MAPI_TOKEN is set, the client sends it as a bearer token. The client refuses to
send it over plain HTTP to an address that is not a loopback address.
Sign in and choose a project v0.3¶
A multi-tenant API (v0.3) needs credentials and a project (Tenancy and authentication).
mapi --profile prod --url https://api.mapi.example login \
--issuer https://accounts.google.com --client-id 1234-abc.apps.googleusercontent.com
mapi --profile prod login --device # no browser here: enter a code elsewhere
mapi --profile ci login --with-token < ci.token # an API token, read from stdin
mapi whoami # who, how, and your projects and roles
mapi loginopens the identity provider in your browser. It uses OpenID Connect and the authorization code with PKCE. The provider redirects to a one-time listener on127.0.0.1.--devicesigns in with a code that you type on a different device.--no-browseronly shows the address.- The CLI saves
--issuer,--client-idand--discovery-urlin the profile. Thus later logins do not need them. - Against a local
MAPI_PROFILE=devstack, usemapi login --issuer https://dev-idp.mapi.localhost --discovery-url http://127.0.0.1:8000/dev/idp. Then select an account on the page that opens. - The CLI keeps the sign-in in
credentials.jsonnext to the config file (mode0600). It renews the sign-in automatically with its refresh token. It sends the sign-in only to the API that it was made for.
mapi login --with-tokenreads an API token from stdin and checks its checksum. Thus it finds an incorrect character before it sends a request. Then it verifies the token withGET /v1/meand saves it in the profile. It writes the config file again with mode0600. An API token in the profile or inMAPI_TOKENhas priority over a browser sign-in.mapi whoamishows who you are and how you signed in. It also shows each project where you can act, with your role there.mapi logoutremoves the sign-in and revokes its refresh token at the identity provider. It also removes the token of the profile.--revokealso revokes that token on the server.
Each v0.2 resource (datasets, specs, runs, models, plots) is now in a project. mapi use
checks that you are a member. Then it saves the selection in the profile. The CLI sends the
project as X-Mapi-Project, but only on project-scoped requests. --project overrides it
for one command. MAPI_PROJECT overrides it for one shell. An API token acts only in its own
project.
mapi use acme/growth # sent as X-Mapi-Project from now on
mapi --project acme/retail runs ls # another project, for one command
mapi use # show the selection and where it came from
Tokens, usage and cost v0.3¶
mapi tokens create budget-planner -s score:geo-mmm-prod -s models:read \
--expires-in-days 30 --rate-limit 120 > planner.token # the secret, once, on stdout
mapi tokens ls
mapi tokens revoke tok_01jaf3r1s2t3v4w5x6y7z8a9b0 # asks first; --yes for scripts
mapi usage --group-by resource_class # this month: cost, compute, quota headroom
mapi usage --tenant acme --period day # the whole tenant today (tenant admins)
mapi runs get run_01jaf3q2x8m9v7k5h4g3f2e1d0 # includes the run's metered cost
mapi tokens create shows the secret of the new token one time, alone on stdout. Thus, if
you redirect stdout to a file, the file contains exactly the token. --save stores the
token in the profile instead. No other command ever shows a token. Lists, whoami and
config show use the redacted form mapi_<prefix>_….
mapi usage shows these data:
- The exact cost of the period, in integer micro-units of the currency. A named price table gives the prices.
- The vCPU-seconds and GiB-seconds behind the cost.
- How much of each quota is used, and when it resets.
mapi runs get and mapi runs ls show the cost of each run. While the cost is still an
estimate, it has a ~.
When the API answers 429, the client does these actions:
- For
RATE_LIMITED, the client waits and then tries again. It waits for theRetry-Afterof the server, and then uses exponential back-off. - For
QUOTA_EXCEEDED, the client stops immediately. It shows the reason and the time when the quota resets (retry after 1h 30m). With--json, it also givesretry_after_seconds.
Operators v0.3¶
Platform operators use mapi admin to manage tenants, quotas, kill switches and executors.
Each change shows a before-and-after table and asks for confirmation. For runbooks, --yes
skips the confirmation. The server audits each change. Kill-switch changes need --reason.
mapi admin kill-switches set --untrusted-code off --reason "incident 2026-10-15"
mapi admin quotas set tenant acme --vcpu-seconds-per-day 172800 --concurrent-runs 40 \
--storage 200GiB --note "beta customer"
mapi admin tenants update acme --status suspended --reason "payment overdue"
mapi admin executors ls
mapi admin executors disable cloudrun-jobs --reason "incident 2026-10-15: contain"
mapi admin audit --tenant acme --action token.create --since 2026-10-01
mapi admin quotas set replaces the full policy of a subject. It removes the limits that you
do not give. The tier defaults and the other levels still apply.
Upload data¶
mapi datasets upload does these steps:
- If the dataset does not exist, it creates the dataset.
- It sends the file to the signed URL that the API returns.
- It starts the sandboxed ingest run.
- It waits until the version is ready.
CSV and Parquet files need --mapping mapping.yaml. This file is an IngestMapping that
gives the column of each dim and variable:
python scripts/seed.py --export demo/ # the E33 tables, score payloads and spec
mapi datasets upload demo/eu_media_future.zarr.zip --name eu_media_future
mapi datasets ls
A zip of images with a manifest table (v0.14) also needs a mapping, with
format: image_folder. Refer to Image data. For a folder of
images and for network weights (v0.15), use mapi datasets upload-images and
mapi datasets upload-weights (see Image collections and weights).
Fit and follow¶
mapi fit SPEC --remote @ creates the spec. If the text changed, it adds a revision. Then it
submits a fit run and follows its event stream until the run ends. It shows warnings,
diagnostics and metrics when they arrive. With --no-wait, the command returns after it
submits the run. mapi runs watch RUN follows a run at a later time.
mapi check demo/eu-geo-mmm.yaml --remote @ # the server's static validation
mapi fit demo/eu-geo-mmm.yaml --remote @ # create or revise the spec, fit, follow
mapi runs ls --kind fit --limit 3
mapi runs cancel RUN asks for cancellation. mapi runs retry RUN --resource-class L starts
a new run from a run that failed.
From v0.11, mapi runs watch and mapi fit --remote also show the metrics that the model
logs. They show a maximum of one metrics line each 5 seconds, for example
metrics loss=1.23 (step 400).
Track metrics, params and tags v0.11¶
Each run keeps metrics, params, tags, a name and a note. To see them, do these steps:
- Show the metric series of a run:
mapi runs metrics RUN. - Show the points of one key:
mapi runs metrics RUN --key step_size --points 200. - Show the params:
mapi runs params RUN.
You can add values to a run, also after it finished. You need the runner role. A token needs
the runs:write scope.
mapi runs log-metric RUN revenue_lift 0.042 --label region=north
mapi runs log-param RUN analyst kim
mapi runs tag RUN stage=production team=growth --delete old_tag
mapi runs rename RUN "weekly sales, adstock 4"
echo "Holiday weeks removed." | mapi runs note RUN -
To find runs by their tracking data, use the options of mapi runs ls:
mapi runs ls --filter 'metric.rmse < 12' --filter 'param.fit.engine = nutpie' \
--order-by metric.rmse --column metric.rmse --column param.settings.adstock.l_max
mapi runs ls --tag stage=candidate --name adstock --parent RUN
For the grammar of --filter, --order-by and --column, see
Search runs.
Media, experiments and comparison v0.14¶
mapi runs media RUN # key, labels, step, kind, size, caption
mapi runs media RUN --key samples --download out/ # files KEY-LABELS-STEP.EXT
mapi runs log-image RUN holdout_map map.png --step 3 --label split=val --caption "Holdout error"
mapi experiments create "adstock length study" --description "Adstock 2, 4 and 8 weeks."
mapi experiments add "adstock length study" RUN RUN
mapi experiments ls
mapi experiments show "adstock length study"
mapi experiments rename "adstock length study" "adstock study"
mapi experiments archive "adstock study" # unarchive makes it accept runs again
mapi experiments remove "adstock study" RUN
mapi experiments rm "adstock study" # the runs stay
mapi fit spec.yaml --remote @ --experiment "adstock study"
mapi workflows run weekly-readiness -i data=dataset://growth/sales@latest \
--experiment "adstock study" # the node runs join it too
mapi runs ls --experiment "adstock study" --column metric.rmse
mapi runs compare RUN RUN RUN --key loss --key rmse --agg min
mapi runs views save "best fits" --filter 'metric.rmse < 12' --order-by metric.rmse \
--column metric.rmse
mapi runs views ls
mapi runs ls --view "best fits"
mapi runs views rm "best fits"
An experiment argument (EXP) is an id or the exact name of the experiment. mapi runs
compare shows a table of the metrics (one column for each run), then the params that are
different (--all-params shows all params). mapi runs ls --view uses the search of the
view. The other options add to the search or replace a part of it. mapi runs watch shows a
line for each image that the run logs (a maximum of one line each 5 seconds).
Image collections and weights v0.15¶
mapi datasets missing-images product_photos ./photos # new and present images
mapi datasets upload-images product_photos ./photos --label-from-folder --size 64x64 --wait
mapi datasets upload-images product_photos ./photos --manifest labels.csv \
--label-column label --split-column split --state photos.upload.json
mapi datasets upload-images product_photos ./photos --no-base # upload all images again
mapi datasets upload-weights tiny-resnet resnet.safetensors --arch arch.json
upload-images uploads only the images that the base version does not have (by default the
latest ready collection version). If the upload stops, type the same command again. With
--state, the command skips the parts that arrived and signs the expired URLs again. The
options are in Image data: collections.
upload-weights uploads a safetensors file as a weights dataset (the mapping
{format: safetensors}). --arch gives the architecture when the file has no mapi_arch
metadata. Read Deep learning.
--resource-class accepts GPU wherever the CLI offers the option, for example
mapi runs retry RUN --resource-class GPU. Use it only for a model that uses a GPU. See
Deep learning: use the GPU class.
Score¶
cat > forecast.yaml <<'EOF'
apiVersion: mapi/v1
kind: ScoreRequest
model: model://default/eu-geo-mmm@latest
mode: forecast
horizon: {dim: time, periods: 8}
data: dataset://default/eu_media_future@latest
side_tables: {fx: dataset://default/fx_daily@latest}
output: {kind: expected, summary: [mean, hdi_90]}
EOF
# the CLI has no `models` command yet: take the model id and version from the API
# (with the same credentials as the CLI when MAPI_TOKEN is set)
AUTH=(-H "X-Mapi-Project: ${MAPI_PROJECT:-default/default}")
[ -z "${MAPI_TOKEN:-}" ] || AUTH+=(-H "Authorization: Bearer $MAPI_TOKEN")
MODEL=$(curl -s "${AUTH[@]}" "${MAPI_API_URL:-http://127.0.0.1:8000}/v1/models" \
| jq -c '.items[] | select(.name == "eu-geo-mmm")')
mapi score forecast.yaml --remote @ --model "$(jq -r .id <<<"$MODEL")" \
--version "$(jq -r .latest_version <<<"$MODEL")" -o forecast.zarr.zip
mapi score --remote @ sends Prefer: wait=60. To change the time, use --wait. If the run
takes longer, the command follows the run. It shows the outputs with their sizes and CRC32C.
With -o, it downloads the result tree and checks it against that CRC32C.
The request must give data to score: data, inline values, a scenario dataset or a
forecast horizon. If it gives none of them, the server refuses the request before a run
starts (SCHEMA_INVALID on /data, "the score request has no data").
Endpoints, webhooks and sharing v0.4¶
mapi endpoints promote geo-mmm-prod model://growth/eu-geo-mmm@v3 # asks first; --yes skips
mapi endpoints ls
mapi endpoints schema geo-mmm-prod --example > call.json # a valid score call
mapi endpoints score geo-mmm-prod call.json -o result.zarr.zip
mapi endpoints score geo-mmm-prod --mode forecast --periods 8 --draws 100
mapi endpoints score geo-mmm-prod --data plan.nc # inline XrJSON (≤ 5 MB)
mapi endpoints snippets geo-mmm-prod -l python > score.py
mapi endpoints rollback geo-mmm-prod --reason "v3 over-forecasts"
promote goes through the promotion gate. A
scorecard with warnings needs --override --reason TEXT from a signed-in project admin. The
gate blocks a scorecard that fails. Promotions and rollbacks change what each integration
that calls the alias receives. Thus both commands show the current version and ask before
they act.
score sends a JSON EndpointScoreCall. The call comes from a file, from stdin (-) or
from --example. Flags set these values:
- The mode and the horizon.
--data/--scenario: adataset://reference, an XrJSON.json, a.zarr.zipor a netCDF file. The command sends the file inline.--draws.
score waits in the same way as mapi score --remote. -o downloads the result tree. With
one --language, snippets shows only the code.
mapi endpoints schema ts-forecast # the Input table's columns
mapi endpoints forecast ts-forecast input.csv # actuals + blank-target future rows
mapi endpoints forecast ts-forecast --actuals new.csv --periods 6
mapi endpoints forecast ts-forecast --actuals new.csv --future 1961-04-01 --future 1961-05-01
mapi endpoints forecast ts-forecast input.csv --dry-run # print the call, send nothing
forecast sends actuals and the dates to forecast
without a new fit. The CSV has a header row with the columns of the input table of the
endpoint: the time column, the target and the drivers. schema lists them.
- Rows with a target value are actuals.
- Rows after the actuals with an empty target are the forecast.
- If there are no such rows, the command adds
--periods(default 8) after the last actual. - The command carries empty drivers on future rows forward (
--future-covariates).
The command shows the data that the forecast used ("Forecast updated with 3 actuals …") and
the summary table. score also shows them.
mapi webhooks create https://hooks.example.com/mapi -e endpoint.promoted -e run.failed > hook.secret
mapi webhooks ls
mapi webhooks deliveries WEBHOOK_ID --status failed
mapi webhooks replay WEBHOOK_ID DELIVERY_ID
mapi webhooks update WEBHOOK_ID --enable # back on after --inactive or an auto-disable
mapi webhooks update WEBHOOK_ID -e run.failed --description "on-call"
mapi webhooks rotate WEBHOOK_ID > hook.secret # asks first; the old secret signs for 24 h
mapi webhooks rm WEBHOOK_ID # asks first
create and rotate show the signing secret of a webhook one time, alone on stdout, as for
tokens. Lists show whsec_…<last 4>. update changes the events, --url or
--description. -e replaces the full list of events. --enable/--disable turns
deliveries on or off.
A webhook that you created with --inactive goes back on with --enable. This also applies
to a webhook that the platform disabled automatically after many failures. --enable also
resets the failure count. Delivery responses are the text of the receiver. The CLI shows them
with control sequences removed. Receiving webhooks tells how to
verify deliveries.
mapi plots render --model MODEL_ID --version 3 --plot mmm.response_curves -f pdf -o curves.pdf
mapi plots render --saved PLOT_ID --width 1200
mapi plots embed PLOT_ID --expires-in-days 30 --allow-origin https://bi.example.com
mapi plots embeds PLOT_ID
mapi plots revoke PLOT_ID EMBED_ID # asks first
render draws the plot in the sandbox (vl-convert) and downloads the file. embed shows the
link one time. The link contains its token (Sharing plots).
Guided mode and business priors v0.4¶
mapi guided templates [geo_mmm]
mapi guided detect geo_mmm --csv media.csv # or --dataset dataset://growth/media@v2
mapi guided draft geo_mmm --name eu-geo-mmm --dataset eu_media --csv media.csv --detect \
-a spend=tv_spend,search_spend -a holdout_periods=8 --yaml-out spec.yaml
mapi priors preview --beliefs beliefs.yaml --spec SPEC_ID --revision 2 -o priors.json
detect and draft --csv profile the file locally. They find the types, counts, ranges
and some sample values of each column. They send only those summaries, as the web app does.
--detectfills each answer that detection is sure of.-a QUESTION=VALUEanswers one question, or overrides the answer. Usea,b,cfor lists and JSON for numbers.
A draft stores nothing. Examine spec.yaml. Then upload the data with the mapping
(--mapping-out) and fit. priors preview changes ROI ranges or contribution-share ranges
into model priors in a sandboxed run. It shows what the model then believes, for each channel
(Guided modelling).
v0.12 and v0.13 add the templates mediated_mmm, multi_kpi_mmm, campaign_impact and
geo_lift (see Measure the effect of a change). Upgrade the CLI to v0.13 or
later. A v0.12 CLI cannot read the list of templates from a v0.13 server: mapi guided
templates fails.
Sign-up and your workspace v0.4¶
mapi --url https://api.mapi.example signup --email ana@acme.example --name "Ana Analyst" --accept-terms
mapi --url https://api.mapi.example verify-email mev_… # the token from the e-mail link
mapi tenant status # verification, any scheduled deletion
mapi tenant export -o acme-export.zip # GDPR export, waited for and downloaded
mapi tenant delete # type the tenant id to confirm
mapi tenant delete --cancel # within the grace period
signup and verify-email send no credentials. tenant delete tells what the platform
purges and what it keeps. Then it asks you to type the tenant id. Scripts give
--confirm TENANT. The tenant is --tenant. If you do not give it, the tenant is the tenant
of the selected project. If there is no selected project, it is your only tenant
(Deleting and exporting data).
Workflows, governance and explorers v0.5¶
Help me choose and About cards, in the terminal:
mapi choose # questions, one at a time; Enter skips one
mapi choose -a goal=forecast -a data_shape=one_series -a drivers=yes -a experience=beginner
mapi about ts.sarimax # one item's About card
mapi about ts.sarimax --expert # ... with the maths and references
Workflows: start from the gallery and check the file on the server. Then save it, run it
and watch each node live. If the run fails, --watch exits with status 1. Thus it works in
CI:
mapi workflows templates # the gallery, in plain words
mapi workflows init ts_readiness_arimax --name weekly-readiness # writes weekly-readiness.yaml
mapi workflows validate weekly-readiness.yaml # checked by the server: pointers to every problem
mapi workflows apply weekly-readiness.yaml -m "first version" # create, or save a revision
mapi workflows run weekly-readiness \
--input data=dataset://growth/weekly_sales@latest \
--param 'drivers=["price"]' --param window=104 \
--watch # live node status; exit 1 if the run fails
validate and apply show the sequence in which the nodes will run. This output is from a
local stack, with the document of the cookbook:
weekly-readiness.yaml: valid (23 nodes)
order: adf → kpss → pp → za → seas → folds → holdout → wanders → seasonal → naive → order → sdiff → backtest → fit → diff → compare → dm → acf → select → governance → report → trusted → pack
The cookbook shows the live board of --watch
and the summary at its end. Then examine a run, one node at a time:
RUN=$(mapi --json workflows runs weekly-readiness -n 1 | jq -r '.[0].run_id')
mapi workflows status "$RUN" # nodes, what each found, decisions, outputs
mapi workflows node "$RUN" order # one node: parameters, result, outputs
mapi workflows output "$RUN" diff data --out diff.zarr.zip # a derived dataset, verified
node order
uses search.arma_order@1.0.0
status succeeded
attempt 1
child runs run_01m53hawz719exdgb6kcw5ysp3
params {"d": 1, "exog": ["price"], "max_p": 3, "max_q": 3, "trend": "c", "criterion": "aic"}
result {"best_p": 1, "best_q": 1, "best_order": [1, 1, 1], "criterion": "aic",
"best_score": 430.4823790539326, "n_failed": 0, "suggested_p": 0, "suggested_q": 0}
outputs table: table
This is the output of mapi workflows node "$RUN" order. Here, we folded the JSON onto fewer
lines. The differencing decision gave d = 1 to the search, and the run gave the price
driver. The search selected ARIMA(1, 1, 1) by AIC.
mapi workflows schedules add weekly-readiness "0 6 * * 1" --tz Europe/Berlin \
--input data=dataset://growth/weekly_sales@latest
mapi workflows triggers add weekly-readiness dataset://growth/weekly_sales --debounce 600
mapi workflows schedules ls weekly-readiness
-i name=ref binds a workflow input. When the run starts, the platform pins @latest to a
version. -p name=value sets a parameter. If the value parses as JSON, the CLI sends it as
JSON (-p 'horizons=[1,4,13]'). The workflow cookbook has complete
documents that you can start from.
Since v0.9, mapi workflows templates also lists the recipes for Bayesian and science models.
Start each one with mapi workflows init <id>. The cookbook shows the commands for each one:
| Template | Cookbook section |
|---|---|
sci_spatial_ladder |
Disease map: which spatial model? |
sci_network_ladder |
Network ties: which model? |
sci_phylo_signal |
Trait regression across species |
sci_calibrate_then_design |
Calibrate, then design |
bayes_workflow_audit |
Bayesian workflow audit |
sci_image_model_check |
Image model check |
From v0.13, the template geo_lift_mmm measures a geo-lift test and gives the result to
mmm.bayesian as a lift test. See
Measure the effect of a change.
To get the data of a science case study, use python -m mapi_plugin_science.export <case>.
Then upload the file with mapi datasets upload.
Governance: the check catalog, policies, validations and approval by a second person.
mapi validate model waits for the checks. It shows each result in plain words with the
suggested action. mapi approve needs a signed-in reviewer who did not submit the model:
mapi governance checks # what a policy can require
mapi governance checks --about null.permutation_target --expert
mapi governance policies ls # in force here: tenant-wide first
mapi governance policies create forecast-policy.yaml
mapi validate model model://growth/wf-weekly-readiness-fit@v1 # runs the checks, waits
mapi validations ls --queue # reviewers: what waits for a decision
mapi approve "$VALIDATION" --comment "Null tests convincing; beats naive by 25%"
mapi validations pack "$VALIDATION" --out evidence.html # for the auditor
Explorers and budget plans:
mapi explore dataset dataset://growth/weekly_sales@latest \
-s overview -s stationarity -s ccf -s stl --kpi sales --out views/
mapi explore dataset weekly_sales --show stationarity # one view as JSON
mapi explore model model://growth/wf-weekly-readiness-fit@v1 -s params -s residuals
mapi explore compare model://growth/arimax@v3 model://growth/ets@v1 --horizon 4
mapi optimize model://growth/geo-mmm@v7 --change-pct 0 \
--channel 'tv={"min_multiplier": 0.5, "max_multiplier": 1.5}' \
--objective p10 --frontier 8
These are the forms of a model reference: model://project/name@vN, name@vN, name with
-v N, or a model id. Dataset references have the same forms with dataset://. All
commands accept --json.
Use --json in scripts¶
--json is a global option. It shows one JSON document on stdout instead of tables.
runs watch --json and workflows watch --json show one JSON event on each line. Errors
become {"error": {...}} with exit status 1. Usage errors exit with status 2.
RUN=$(mapi --json runs ls --kind score --limit 1 | jq -r '.[0].id')
mapi --json runs get "$RUN" | jq '{state, attempt, kind}'
mapi runs logs "$RUN" | tail -n 5
The CLI removes ANSI and control sequences from text that came from the server, a plugin or a run log. Thus a hostile log line cannot write over your terminal.
mapi serve¶
mapi serve runs mapi-server dev. It does the database migrations. Then it runs the API and
the orchestrator in one process. It uses an embedded PostgreSQL, unless DATABASE_URL is set.
It uses an in-process GCS shim, unless a shim already listens at MAPI_GCS_ENDPOINT. This is
the smallest way to get an API for the CLI or the client. If you also want the web app, use
make dev (Local deployment).