Examples index¶
Every example in examples/ catalogued in one place. Each entry: file path → what it demonstrates → which concept doc explains it.
Examples come in three flavours:
- CLI (
examples/cli/*.sh) — bash invocations of thedhis2Typer CLI. Run withbash examples/cli/<name>.shwith the venv onPATH(viasource .venv/bin/activateoruv run -- bash ...). - Client (
examples/client/*.py) — Python library usage. Run withuv run python examples/client/<name>.py. - MCP (
examples/mcp/*.py) — FastMCP tool calls through an in-process client. Run withuv run python examples/mcp/<name>.py.
Every example reads the active DHIS2 profile from .dhis2/profiles.toml / ~/.config/dhis2/profiles.toml / DHIS2_PROFILE env (see profiles). Assume a seeded local stack (make dhis2-run) unless stated otherwise.
CLI examples¶
| Example | What it demonstrates | Related docs |
|---|---|---|
metadata_round_trip.sh |
Cookbook — export → jq transform → diff → dry-run → import → live verify → revert | CLI tutorial / metadata plugin |
whoami.sh |
Simplest invocation — dhis2 system whoami + dhis2 system info |
system |
profile_list_verify.sh |
dhis2 profile list / verify / show |
profiles |
profile_oidc_config.sh |
Populate an OAuth2 profile by discovering DHIS2's OIDC endpoints | auth |
profile_oidc_login.sh |
Full OIDC login flow — profile add → login → verify → whoami | auth |
metadata_list_get.sh |
dhis2 metadata list / get + client-side UID generation |
metadata plugin |
metadata_patch.sh |
RFC 6902 JSON Patch — inline --set / --remove and file-based |
metadata plugin |
metadata_export_import.sh |
Cross-instance bundle round-trip (export → import) | metadata plugin |
metadata_export_filter.sh |
Per-resource filters + dangling-reference warning on export | metadata plugin |
metadata_diff.sh |
dhis2 metadata diff — bundle-vs-bundle or bundle-vs-live |
metadata plugin |
metadata_search.sh |
Cross-resource UID / code / name search via dhis2 metadata search <query> |
metadata plugin |
attribute_values.sh |
Cross-resource AttributeValue workflows via dhis2 metadata attribute |
metadata plugin |
options.sh |
OptionSet + Option workflows — dhis2 metadata options get / find / sync |
metadata plugin |
legend_sets.sh |
dhis2 metadata legend-sets — create / get / clone / delete + the seeded LsDoseBand1 coverage dashboards |
legend sets API |
organisation_units.sh |
dhis2 metadata organisation-units + groups + group-sets + levels — tree walk, per-level rename, group + dimension round-trip |
organisation units API |
data_elements.sh |
dhis2 metadata data-elements + groups + group-sets — DE create, rename, legend-set attach, group + dimension round-trip |
data elements API |
indicators.sh |
dhis2 metadata indicators + groups + group-sets — numerator/denominator expression pre-flight, create, group + dimension round-trip |
indicators API |
program_indicators.sh |
dhis2 metadata program-indicators + groups — program-scoped expression validation + group membership (pair, no group-set) |
program indicators API |
category_options.sh |
dhis2 metadata category-options + groups + group-sets — validity-window creation + group + dimension round-trip |
category options API |
data_sets.sh |
dhis2 metadata data-sets + sections — DataSet create, DE attach (with per-set CC override), ordered Section round-trip |
data sets API |
validation_rules_predictors.sh |
dhis2 metadata validation-rules + predictors + their groups — CRUD round-trip for the authoring flip side of maintenance validation run / maintenance predictors run |
validation rules + predictors API |
tracker_schema.sh |
dhis2 metadata tracked-entity-attributes + tracked-entity-types — create a unique-generated TEA + a Person TET and wire them together |
tracker schema API |
tracker_programs.sh |
dhis2 metadata programs — tracker + event Program authoring with PTEA enrollment form + OU scoping |
tracker schema API |
tracker_program_stages.sh |
dhis2 metadata program-stages — stage authoring with ordered PSDE list + reorder + per-DE compulsory flag |
tracker schema API |
messaging.sh |
dhis2 messaging send / get / reply / set-priority / assign / delete — ticket-workflow round-trip |
messaging plugin |
program_rules.sh |
dhis2 metadata program-rule — vars, validate-expression, where-de-is-used |
metadata plugin |
sql_views.sh |
dhis2 metadata sql-view list / get / execute / refresh / adhoc across the VIEW / QUERY / MATERIALIZED_VIEW shapes |
SQL views API |
aggregate_data_values.sh |
Aggregate data values — read / write a single value / bulk file push | aggregate |
tracker_reads.sh |
Tracked entities by type, enrollments, events, bulk import | tracker |
tracker_register_and_followup.sh |
Canonical tracker-program clinic intake — register, log an event, query outstanding enrollments | tracker |
tracker_event_program.sh |
Event-only WITHOUT_REGISTRATION program — standalone events with no enrollment | tracker |
analytics_query.sh |
Aggregated analytics queries + resource-table refresh | analytics |
analytics_outlier_tracked_entities.sh |
Outlier detection + tracked-entity analytics | analytics |
user_administration.sh |
dhis2 user — list / get / invite / reinvite / reset-password |
user plugin |
user_groups_and_roles.sh |
dhis2 user-group + dhis2 user-role admin workflows |
user groups + roles |
route_register_and_run.sh |
dhis2 route lifecycle across every upstream auth type |
auth schemes |
customize_login.sh |
Brand the DHIS2 login page + top menu | customize plugin |
doctor.sh |
dhis2 doctor — probe every BUGS.md gotcha + metadata-health check |
doctor plugin |
maintenance.sh |
dhis2 maintenance — background tasks, cache, cleanup, integrity |
maintenance plugin |
files.sh |
dhis2 files — documents (URL + binary round-trip) + fileResource (MESSAGE_ATTACHMENT round-trip) |
files plugin |
validation_and_predictors.sh |
dhis2 maintenance validation + dhis2 maintenance predictors — expression validation, VR analysis, persisted results, predictor runs |
validation API |
visualizations.sh |
dhis2 metadata viz + dhis2 metadata dashboard — flag-driven viz create, clone, dashboard compose |
visualizations guide |
visualization_screenshot.sh |
dhis2 browser viz screenshot — PNG capture via the Data Visualizer app (needs [browser] extra) |
visualizations guide |
maps.sh |
dhis2 metadata map — thematic choropleth authoring via REST |
maps API |
map_screenshot.sh |
dhis2 browser map screenshot — PNG capture via the Maps app (needs [browser] extra) |
maps API |
apps.sh |
dhis2 apps list / hub-list / hub-url / update --dry-run / update --all / reload over /api/apps + /api/appHub |
apps API |
dev_codegen.sh |
dhis2 dev codegen — regenerate the typed client from a live instance |
codegen |
dev_pat.sh |
dhis2 dev pat create — provision a PAT as admin |
auth |
dev_sample.sh |
dhis2 dev sample ... — inject fixtures + verify end-to-end |
manual testing |
Client examples (Python library)¶
| Example | What it demonstrates | Related docs |
|---|---|---|
bulk_patch_from_csv.py |
Cookbook — apply a CSV of patches concurrently via asyncio.gather + JsonPatchOpAdapter |
metadata plugin |
profile_drift_check.py |
Cookbook — diff metadata between two profiles, exit non-zero on drift (CI template) | metadata plugin |
retry_policy.py |
Cookbook — RetryPolicy for transient 5xx / connection errors on batch workflows |
client library tutorial |
task_await.py |
Cookbook — client.tasks.await_completion blocks on analytics refresh / metadata import / etc. |
client library tutorial |
concurrent_bulk.py |
Cookbook — fan-out patterns (naive gather → bounded semaphore → tuned pool + retries) with live timings | client architecture |
integrity_issues_stream.py |
Cookbook — client.maintenance.iter_integrity_issues streams tagged issues, severity histogram, early-break scan |
maintenance plugin |
system_cache.py |
Cookbook — client.system cache: info() primed on connect, default_category_combo_uid(), per-key setting(), invalidate + refetch |
system API |
files_documents.py |
Cookbook — client.files documents + fileResource round-trip; external URL docs, binary two-step upload, MESSAGE_ATTACHMENT round-trip |
files plugin |
bulk_delete.py |
Cookbook — client.metadata.delete_bulk / delete_bulk_multi for one-call teardown via /api/metadata?importStrategy=DELETE |
metadata accessor |
metadata_patch_bulk.py |
Cookbook — client.metadata.patch_bulk fans out RFC 6902 patches across many UIDs with per-UID failure capture |
metadata accessor |
bulk_save_and_dry_run.py |
Cookbook — client.resources.<res>.save_bulk(items) for typed bulk create/update + client.metadata.dry_run(...) as the pre-commit safety gate |
metadata accessor |
stream_data_values.py |
Cookbook — client.data_values.stream four ways: bytes, sync generator, Path (CSV), 1000-row file with timing |
data values streaming |
stream_analytics.py |
Cookbook — client.analytics.stream_to for JSON / CSV / rawData exports to disk with per-format timing |
analytics streaming |
messaging_with_attachment.py |
Cookbook — client.messaging.send + MESSAGE_ATTACHMENT fileResource pairing; full inbox lifecycle (list, reply, mark-read, delete) |
messaging plugin |
validation_and_predictors.py |
Cookbook — client.validation + client.predictors workflow: expression validation, run analysis, list persisted results, run predictors |
validation API |
whoami.py |
Minimal — default profile → call /api/me |
client library tutorial |
library_only_auth.py |
Library-only auth for PyPI consumers without dhis2w-core |
auth |
profile_resolver.py |
Use a DHIS2 profile from Python via dhis2w-core.open_client |
profiles |
profile_crud.py |
Profile CRUD — in-memory Profile(...) + on-disk add/rename/set-default/remove through the profile-plugin service |
profiles |
oidc_login.py |
OAuth 2.1 authorization-code + PKCE flow; auto-dispatches to Playwright when DHIS2_USERNAME+DHIS2_PASSWORD are set |
auth |
oidc_playwright_login.py |
Fully automated end-to-end OIDC via drive_oauth2_login — CLI subprocess + Chromium IdP form + consent screen |
auth / browser |
list_data_elements.py |
Generated typed resource accessors | metadata CRUD |
enum_round_trip.py |
Generated StrEnums — type-safe access to DHIS2 CONSTANT values | typed schemas |
metadata_filter_order_paging.py |
Full query DSL — filters, rootJunction, order, server-side paging | metadata plugin |
metadata_patch.py |
RFC 6902 JSON Patch — generated accessor + service + adapter paths | metadata plugin |
metadata_export_import.py |
Export + import round-trip via the service layer | metadata plugin |
metadata_diff.py |
service.diff_bundles + diff_bundle_against_instance |
metadata plugin |
metadata_bulk_import.py |
Typed dry-run + real bulk import | metadata plugin |
metadata_search.py |
Cross-resource UID / code / name search via client.metadata.search |
metadata plugin |
metadata_usage.py |
Reverse-reference lookup "what points at this UID?" via client.metadata.usage |
metadata plugin |
attribute_values.py |
AttributeValuesAccessor across every resource with an attributeValues field |
metadata plugin |
options_integration.py |
Every method on OptionSetsAccessor — list / get / find / sync |
metadata plugin |
legend_sets.py |
client.legend_sets.create_from_spec + VisualizationSpec(legend_set=...) — colour bands attached to a throw-away viz |
legend sets API |
organisation_units.py |
client.organisation_units + groups + group-sets + levels — descendants walk, rename-by-level, membership + dimension round-trip |
organisation units API |
data_elements.py |
client.data_elements + groups + group-sets — keyword-arg create, rename, per-item membership, dimension |
data elements API |
indicators.py |
client.indicators.validate_expression pre-flight + numerator/denominator create + group + dimension round-trip |
indicators API |
program_indicators.py |
client.program_indicators + groups — program-scoped expression validation + EVENT/ENROLLMENT create + group round-trip (pair, no group-set) |
program indicators API |
category_options.py |
client.category_options validity-window helper + groups + group-sets round-trip |
category options API |
data_sets.py |
client.data_sets + client.sections — DataSet create, DE attach, ordered Section round-trip |
data sets API |
validation_rules_predictors.py |
client.validation_rules + client.predictors (plus their groups) — CRUD round-trip + group membership |
validation rules + predictors API |
tracker_schema.py |
client.tracked_entity_attributes + client.tracked_entity_types — TEA + TET round-trip with the TETA linkage helpers |
tracker schema API |
tracker_programs.py |
client.programs — tracker Program with PTEA + OU linkage, using the TET + TEA from step 1 |
tracker schema API |
program_rules.py |
Every method on ProgramRulesAccessor — get, vars, validate, where-DE-used |
metadata plugin |
sql_views.py |
SqlViewsAccessor list / get / execute / refresh / adhoc across the three view shapes |
SQL views API |
sql_view_runner.py |
Three ways to use SqlViewRunner — by UID, ad-hoc query, named bindings |
SQL views API |
indicator_crud.py |
Create a typed Indicator with a formula, use it, clean up | metadata CRUD |
data_set_crud.py |
Full CRUD lifecycle for a data set | metadata CRUD |
org_unit_crud.py |
Full CRUD lifecycle for an organisation unit | metadata CRUD |
geojson_org_units.py |
Pull org units as GeoJSON (validated via geojson-pydantic) | metadata CRUD |
push_data_value.py |
Write one aggregate data value against the seeded dataset | aggregate |
tracker_lifecycle.py |
Create a tracked entity with an enrollment + event | tracker |
tracker_clinic_intake.py |
Canonical tracker-program intake via client.tracker.register / add_event / outstanding |
tracker |
tracker_event_program.py |
WITHOUT_REGISTRATION event-only program — one-shot events via add_event without an enrollment |
tracker |
analytics_query.py |
Aggregated analytics + resource-table refresh | analytics |
analytics_events_enrollments.py |
Event + enrollment analytics queries | analytics |
analytics_outlier_tracked_entities.py |
Outlier detection + tracked-entity analytics | analytics |
task_polling.py |
Watch an analytics-refresh job to completion | maintenance plugin |
doctor.py |
Programmatic probe results for CI / monitoring | doctor plugin |
user_administration.py |
User administration via the Python client | user plugin |
user_groups_and_roles.py |
User groups + user roles via the Python client | user groups + roles |
sharing.py |
Typed sharing helpers — read + replace on any object | sharing |
customize_login.py |
Brand a DHIS2 instance programmatically | customize plugin |
error_handling.py |
Dhis2ApiError, WebMessage conflicts, AuthenticationError |
errors |
bootstrap_zero_to_data.py |
End-to-end — zero org unit to a data value in one script | client library tutorial |
viz_create_basic.py |
Simplest visualization spec → create → verify axes | visualizations guide |
viz_multiline_by_province.py |
Multi-line time-series with analytics-probe sanity check | visualizations guide |
viz_pivot_and_kpi.py |
PIVOT_TABLE + SINGLE_VALUE default placements side-by-side | visualizations guide |
viz_clone_and_modify.py |
Clone an existing chart, verify independence | visualizations guide |
dashboard_compose.py |
Assemble a dashboard from scratch with typed DashboardSlots |
visualizations guide |
map_create_choropleth.py |
Build a thematic choropleth from a typed MapSpec + MapLayerSpec |
maps API |
apps.py |
client.apps.list_apps / hub_list / get_hub_url — library surface for the apps plugin |
apps API |
MCP examples¶
| Example | What it demonstrates | Related docs |
|---|---|---|
whoami.py |
whoami + system_info MCP tools in-process |
MCP |
profile_tools.py |
Read-only profile MCP tools |
profiles |
metadata.py |
Browse metadata via MCP | metadata plugin |
metadata_patch.py |
RFC 6902 JSON Patch via the metadata_patch tool |
metadata plugin |
metadata_diff.py |
metadata_diff tool against two bundles |
metadata plugin |
metadata_export_import.py |
Bundle round-trip via MCP tools | metadata plugin |
metadata_search.py |
metadata_search — cross-resource UID / code / name lookup for agents |
metadata plugin |
metadata_usage.py |
metadata_usage — "what references this UID?" reverse lookup for agents |
metadata plugin |
legend_sets.py |
metadata_legend_set_* — list / create / get / delete via MCP |
legend sets API |
organisation_units.py |
metadata_organisation_unit_* — tree walk + levels + group + group-set via MCP |
organisation units API |
data_elements.py |
metadata_data_element_* — DE + group + group-set round-trip via MCP |
data elements API |
indicators.py |
metadata_indicator_* — expression validation + create + group + group-set via MCP |
indicators API |
program_indicators.py |
metadata_program_indicator_* — program-scoped expression + group round-trip via MCP |
program indicators API |
category_options.py |
metadata_category_option_* — validity window + group + group-set via MCP |
category options API |
data_sets.py |
metadata_data_set_* + metadata_section_* — DataSet + Section round-trip via MCP |
data sets API |
validation_rules_predictors.py |
metadata_validation_rule_* + metadata_predictor_* (plus groups) — CRUD round-trip via MCP |
validation rules + predictors API |
tracker_schema.py |
metadata_tracked_entity_attribute_* + metadata_tracked_entity_type_* — TEA + TET round-trip via MCP |
tracker schema API |
tracker_programs.py |
metadata_program_* — tracker + event Program authoring via MCP |
tracker schema API |
aggregate_data_values.py |
GET / SET / DELETE data values via MCP | aggregate |
tracker_reads.py |
Discover TET types, list entities/events via MCP | tracker |
tracker_workflow.py |
Agent flow — tracker_register, tracker_add_event, tracker_outstanding for a tracker program |
tracker |
analytics_query.py |
Aggregated analytics + refresh via MCP | analytics |
analytics_events_enrollments.py |
Event + enrollment analytics via MCP | analytics |
analytics_outlier_tracked_entities.py |
Outlier detection + tracked-entity analytics via MCP | analytics |
maintenance.py |
Tasks, cache, cleanup, data-integrity via MCP | maintenance plugin |
route_register_and_run.py |
Route CRUD + run via MCP | auth schemes |
doctor.py |
Structured probe results for an agent via doctor_run |
doctor plugin |
user_administration.py |
User plugin MCP tools | user plugin |
sharing_and_user_groups.py |
Sharing + user-group admin via MCP | user groups + roles |
customize_login.py |
Branding via MCP | customize plugin |
apps.py |
apps_list, apps_hub_list (plus apps_install_*, apps_uninstall, apps_update{,_all}, apps_hub_url_{get,set} available) |
apps API |
External plugin example¶
examples/plugin-external/ — a minimal runnable external plugin (own pyproject.toml, entry-point registration, CLI + MCP hooks). See external plugins for the contract.
How example coverage maps to features¶
- Every top-level CLI domain has at least one example. See CLI reference for the full command tree.
- Every plugin with a service layer has both a CLI and client example. Pairs are intentional — the CLI shows the user-facing path, the client shows what library callers do.
- Every MCP tool has at least one example call showing the expected input shape + how to unpack the
structured_contentreturn.
When adding a new plugin / command / MCP tool: update this file alongside the feature PR so the catalogue stays in sync.