Skip to content

Examples index

Learning path · step 5 of 8 — Curated task index. Prev: Python tutorial. Next: API reference. examples/{cli,client,mcp,fhir}/ is the source of truth for what's on disk; this page is the curated headline view.

One copy of each example, running against DHIS2 v41, v42, and v43 alike. An example that exists for a single major lives under that major's subdirectory — examples/client/v43/ for the v43 schema divergences, examples/client/v41/ for the v41 wire quirks; see Schema diff: v41 -> v42 -> v43 for what they demonstrate.

Each entry below: file path → what it demonstrates → which concept doc explains it. This page is curated — it covers the headline examples per topic; not every single file shows up here. ls examples/{cli,client,mcp,fhir}/ is the source of truth, and each surface directory has a README of its own.

Examples come in four groups — the three surfaces, plus FHIR, which carries four of its own:

  • CLI (examples/cli/*.sh) — bash invocations of the d2w Typer CLI. Run with bash examples/cli/<name>.sh with the venv on PATH (via source .venv/bin/activate or uv run -- bash ...).
  • Client (examples/client/*.py) — Python library usage. Run with uv run python examples/client/<name>.py.
  • MCP (examples/mcp/*.py) — FastMCP tool calls through an in-process client. Run with uv run python examples/mcp/<name>.py.
  • FHIR (examples/fhir/{cli,client,engine,igs}/) — the FHIR surface, grouped on its own because it is its own product: cli/ and client/ are the two shapes of caller for d2w fhir, engine/ is the evaluation engine, which has no DHIS2 in it at all, and igs/ holds nine complete project trees, one per feature story, which are also the catalog d2w fhir init --template scaffolds from.

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.

FHIR examples

d2w fhir turns a DHIS2 instance's metadata into a FHIR Implementation Guide, serves the compiled guide as a read-and-capture endpoint, and posts what that endpoint captured back into DHIS2. dhis2w-fhir and dhis2w-fhir-serve are not per-version packages, so this group is one copy that runs on every major. The narrative these sit under is the d2w fhir guide series, which opens at the Introduction.

The headline rows are below. The Python library path has fifty-four examples in all — grouped from "build a response from my own data" through reading a form, converting to DHIS2, sending, evaluating over a served guide, driving the toolchain, and embedding the facade in your own process — catalogued in examples/fhir/client/README.md. The evaluation engine has nine of its own, catalogued in examples/fhir/engine/README.md.

Example What it demonstrates Related docs
fhir/cli/init.sh d2w fhir init — scaffold a dockerized SUSHI IG project, offline, with the identity and selection dials Set up an IG project
fhir/cli/init_from_template.sh d2w fhir init --list-templates / --template — scaffold from a guide already generated against an instance, so the project compiles and serves without reaching one Start from a template
fhir/cli/init_refresh.sh d2w fhir init --refresh — bring an existing project's scaffold-managed files up to date without losing a line Set up an IG project
fhir/cli/generate_full_run.sh d2w fhir generate — every target of the IG source off one pass over the instance Generate the IG source
fhir/cli/generate_json_report.sh d2w --json fhir generate — the typed GenerateFullReport on stdout, read with jq: a row per target, and the run's distinct notes grouped by the decision each records Generate the IG source
fhir/cli/generate_foundation.sh d2w fhir generate foundation — the instance-independent artifacts, with no client opened Generate the IG source
fhir/cli/generate_option_sets.sh d2w fhir generate option-sets — one named target alone: the option-set terminology as pre-built JSON Generate the IG source
fhir/cli/generate_stale_compile.sh d2w fhir generate — an unchanged regenerate keeps ig/fsh-generated/, one that rewrites a FSH source removes it and says so, offline Generate the IG source
fhir/cli/generate_hostile_names.sh d2w fhir generate --substitute-hostile-names — a DHIS2 name carrying < refuses the run, then publishes as the words it stands for Generate the IG source
fhir/cli/generate_spaced_codes.sh d2w fhir generate --substitute-hostile-names — a DHIS2 code carrying a space publishes hyphenated, with the DHIS2 code stated beside it as a dhis2-code property Generate the IG source
fhir/cli/validate.sh d2w fhir validate — the FHIR-safety gate over an instance's codes and names, exit 1 on errors Validate the instance
fhir/cli/validate_code_source.sh d2w fhir validate --code-source code — preview what switching concept codes to DHIS2 codes would cost Validate the instance
fhir/cli/check_artifacts.sh d2w fhir check-artifacts — the build refusal read off the artifacts on disk: a clean project, then one stale resource, exit 1 in seconds, offline Build and publish the guide
fhir/cli/serve.sh d2w fhir serve — compile the IG, serve it as a FHIR read + capture facade, post a generated load set, read the receipts back (needs the [serve] extra + docker; skipped by default) Serve the guide
fhir/cli/evaluate.sh POST /facade/evaluate and POST /$evaluate over a served guide, from curl — the OperationDefinition the contract lives in, FHIRPath over a stored form, a parse failure answered 200 with its line and column, and the Parameters a CQL library comes back as FHIRPath
fhir/cli/serve_auth_postures.sh d2w fhir serve --auth - the four postures a facade takes towards a caller: the bind refusal an absent key earns, a static bearer token, the caller's own DHIS2 credentials with the register read as them, and the jwt issuer Secure the facade
fhir/client/read_register_as_yourself.py The register read under the caller's own DHIS2 credentials - what the dhis2 posture changes about who sees whom Secure the facade
fhir/cli/registers_many_types.sh Many tracked entity types on one instance, two of them published as Device: one register serving the union, _tag narrowing it to one type, and the checklist naming every type nobody typed (creates and removes its own metadata; skipped by default) Custom subject types
fhir/cli/serve_projection_search.sh [serve.search] backend = "projection" - a register search answered from the synced copy: _content, the X-DHIS2W-Projection-As-Of header, and the refusal the live backend answers instead Serve the guide
fhir/cli/serve_attribute_filter.sh d2-attribute={attributeUid}\|{value} - the register filtered by what a record holds: the attributes each register declares as filterable at /metadata and /facade/uiconfig, the counts a filter narrows to, a prefix matching nobody, two filters ANDed, an undeclared attribute refused by name, and the same records from both search backends Serve the guide
fhir/cli/serve_record.sh GET /facade/tracked-entities/{uid}/events - one tracked entity's own record: every event of its enrollments as the response its programme stage's published form describes, how long the record is, one event on its own, the parameters the surface refuses, and the events dial that withholds the record while identity is still served Consume the FHIR API
fhir/cli/serve_data_set_responses.sh GET /facade/data-sets/{uid}/responses - what DHIS2 holds for one data set, at one organisation unit, over the periods the request names: each reporting key as the response the data set's published form describes, the cells typed by that form, one reported form on its own, the bounds a read is refused without, the period count one read may name, and the responses dial that withholds the values while the forms stay published Consume the FHIR API
fhir/cli/summary.sh $summary against a served guide - one person's International Patient Summary by tracked entity UID, the same document found by identifier, and what the caveat beside it says Consume the FHIR API
fhir/cli/corrections.sh [forward] corrections / [forward] withdrawals - a submission marked amended or entered-in-error refused at the capture door with the key named, and received once the project states it Forward captures into DHIS2
fhir/cli/withdraw.sh d2w fhir withdraw - take back from DHIS2 the event a forwarded receipt landed: the dry run, the commit, and the spool's fourth state (binds a port; writes; skipped by default) Forward captures into DHIS2
fhir/cli/sync.sh d2w fhir sync — fill a durable copy of the DHIS2 register as FHIR on disk: dry run, the initial materialization, the incremental cursor run, and --rebuild Serve the guide
fhir/cli/forward_dry_run.sh d2w fhir forward — the default: DHIS2 judges every payload under its own validate-only mode, nothing is written, and the queue is as long as it was (needs docker; skipped by default) Forward captures into DHIS2
fhir/cli/forward_import.sh d2w fhir forward --import — the committing drain, and the three states it files a receipt into (needs docker; writes to the instance; skipped by default) Forward captures into DHIS2
fhir/cli/forward_overwrites.sh The two postures a drain takes towards a value already sent - allow names it, refuse queues the response (needs docker; writes; skipped by default) Forward captures into DHIS2
fhir/cli/forward_completeness.sh Data set completeness: what a completed aggregate response registers, and the dial that turns it off (needs docker; writes; skipped by default) Forward captures into DHIS2
fhir/cli/doctor_probe.sh d2w fhir doctor — the whole chain against one instance over a small representative selection, one verdict (skipped by default) Check an instance with doctor
fhir/cli/doctor_all_targets.sh d2w fhir doctor --all-targets — the same chain over every data set, every program, and every organisation-unit level (skipped by default) Check an instance with doctor
fhir/cli/doctor_live_oracle.sh d2w fhir doctor --live — the oracle: served resources deep-compared against the instance (skipped by default) Check an instance with doctor
fhir/cli/doctor_report.sh d2w fhir doctor --workspace — keep the run's workspace and hand over its markdown report (skipped by default) Check an instance with doctor
fhir/cli/doctor_json.sh d2w --json fhir doctor — the typed DoctorReport on stdout, for jq and for CI (skipped by default) Check an instance with doctor
fhir/cli/spool.sh d2w fhir spool + d2w fhir requeue — read the capture queue and put a refused receipt back in it, with no DHIS2 connection and no profile Forward captures into DHIS2
fhir/client/generate_ig.py Generate a whole IG from Python — load_project + generate_full, and the GenerateFullReport consumed as a model dhis2w_fhir API reference
fhir/client/consume_facade.py Plain httpx2 against a running facade — /metadata, search, $generate, POST a capture, read the receipt and /facade/spool Consume the FHIR API
fhir/client/read_metadata_health.py GET /facade/metadata-health off a live facade — the validate findings with the DHIS2 field at fault and what each grade costs, plus translation coverage per locale Capture in the browser
fhir/client/send_with_the_client.py FacadeClient against a running facade — $generate a draft, submit_response it, read the CaptureReceipt id and warnings, read the receipt back typed dhis2w_fhir API reference
fhir/client/search_with_the_client.py The read half of the same client — canonical_resource_types off /metadata, a typed ResourceQuery against the forms and against the register, and resolve turning a canonical into the resource that holds it dhis2w_fhir API reference
fhir/client/evaluate_with_the_client.py evaluate with the typed contexts — InlineResourceContext.over a draft that is stored nowhere, StoredResourceContext over a form the facade holds, and the diagnostic an unparseable expression is answered with rather than raised on FHIRPath
fhir/client/authenticate_with_the_client.py BearerToken against a facade started with --auth token — the open reads, the 401 with no credential, the 401 with the wrong one, and the receipt the right one earns Run a secured facade
fhir/client/handle_refusals_with_the_client.py FacadeError read typed — the 404 a resource nobody holds raises and the 422 a response answering an unpublished form raises, both through status_code, issues, and diagnostics dhis2w_fhir API reference
fhir/client/evaluate_via_facade.py Plain httpx2 against a running facade's POST /facade/evaluate — one FHIRPath call, one CQL library, and one expression that will not parse Consume the FHIR API
fhir/client/evaluate_stored_resource.py The stored context — FHIRPath one-liners counting a DHIS2 data set's sections, data elements and category-combination cells off the served Questionnaire, and the 404 a resource nobody holds earns FHIRPath
fhir/client/evaluate_registered_person.py The registered context — a chart review of one tracked entity read live out of DHIS2, written as CQL from the guide's own published vocabulary CQL
fhir/client/evaluate_as_parameters.py The $evaluate operation's Parameters answer — one parameter per define, part entries per value, an OperationOutcome part per refusal Consume the FHIR API
fhir/client/evaluate_operation_contract.py The operation discovered rather than documented — /metadata names it, OperationDefinition/serve-evaluate states its parameters and cardinalities, and a request built to that contract answers Consume the FHIR API
fhir/client/evaluate_compiled_library.py ELM as the interchange format — one library compiled locally with ELMSerializer and run on the facade as JSON, compared define by define against its own source CQL
fhir/client/forward_spool.py Dry-run a drain from Python — forward_responses, and the ForwardReport counts, outcomes, and rejection reasons Forward captures into DHIS2
fhir/client/minimal_facade.py Facade ladder, level one — one route that translates a capture, posts it, and hands back DHIS2's verdict under DHIS2's own status Build your own facade
fhir/client/basic_facade.py Facade ladder, level two — one client held for the process in a FastAPI lifespan, settings resolved at startup, /health, and a log line per verdict Build your own facade
fhir/client/complex_facade.py Facade ladder, level three — the real spool primitives: a durable receipt, 201 before DHIS2 is asked, a background drain, and GET /receipts/{id} Build your own facade
fhir/client/advanced_facade.py Facade ladder, level four — tracker routing, the strict/lenient dial as app config, overwrite naming on drains, and a small /metadata that is not a CapabilityStatement Build your own facade
fhir/client/embed_the_facade.py The facade as a library — create_app driven over an ASGI transport, reading /metadata and the published forms with no socket bound Embed the facade
fhir/client/capture_headless.py A capture with no server — $generate, POST, the receipt read back, and the spool file it left on disk Embed the facade
fhir/client/forward_headless.py The drain from inside your own process — the caller's own DHIS2 connection handed in, and every dial stated as an argument Embed the facade
fhir/client/projection_local_store.py The local storage layer — run_sync into the SQLite projection, then the watermark, a page, an identifier search, and membership through ProjectionStore The materialized projection
fhir/client/embed_in_fastapi.py The facade's routers mounted inside a caller's own FastAPI application, behind the caller's own authentication dependency Embed the facade
fhir/client/build_aggregate_response.py The minimal aggregate capture — a data set's numbers for one period at one organisation unit, built in typed Python The capture contract
fhir/client/build_registration_response.py Registering a person and enrolling them, minting both DHIS2 UIDs client-side The capture contract
fhir/client/identity_nominations.py [ips.identity] read over a real person — a nominated name filled, a sex value the gender map does not answer for, and a birth date stating its own absence What goes in
fhir/client/ips_document.py One person's tracker record assembled into an IPS-shaped FHIR document Bundle — one mapped section, three required ones stating absence, and the reference check that proves the document closes The IPS document

Evaluate

dhis2w-fhir-engine evaluates FHIRPath, CQL, and ELM over FHIR-shaped data, and scores CQL quality measures into a FHIR R4 MeasureReport. It has no DHIS2 dependency and no web framework, so eight of these nine run instantly against an inline Bundle with nothing else installed. The narrative they sit under is the 501 pages of the guide series.

Example What it demonstrates Related docs
fhir/engine/fhirpath_basics.py Paths, where(), first(), count(), exists() over one Patient — and why every expression answers with a collection FHIRPath
fhir/engine/fhirpath_over_bundle.py ofType() over a whole Bundle: pick a resource type out of the mix, filter it, count what is left FHIRPath
fhir/engine/cql_library_structure.py What each CQL header line declares — library, using, include, codesystem, valueset, code, parameter — and that nothing runs until a definition is asked for by name CQL
fhir/engine/cql_retrieves.py [Patient] and [Immunization], then the same retrieves under context Patient: one evaluation per person, each seeing only their own records CQL
fhir/engine/cql_terminology.py A ValueSet scoping a retrieve, resolved outside the library — plus $validate-code and memberOf asked of the terminology service directly CQL
fhir/engine/cql_intervals.py Interval literals, closed and open bounds, the timing vocabulary, and a "Measurement Period" parameter the caller replaces without editing the library CQL
fhir/engine/measure_report.py The populations, proportion versus cohort scoring, the per-person decisions, and to_fhir() rendering a FHIR R4 MeasureReport Quality measures
fhir/engine/elm_round_trip.py CQL compiled to ELM JSON and run back from the ELM, with every answer compared across both evaluators dhis2w_fhir_engine API reference
fhir/engine/e2e_measure_from_dhis2.py The whole chain: read a seeded Child Programme cohort, map tracked entities to Patient and weight data values to Observation, score a measure, check the counts against DHIS2's own records (needs make dhis2-run) Quality measures

Full guides

Where the scripts above show one command or one library call apiece, examples/fhir/igs/ holds nine complete d2w fhir init project trees — a fhir.toml, a SUSHI skeleton, a Makefile, a Dockerfile — each selecting one feature story out of the seeded local instance. Every tree is committed as its inputs alone; nothing d2w fhir generate or SUSHI writes is. make verify-igs refreshes, validates, generates, and dockerized-SUSHI-compiles all nine on demand.

Guide What it demonstrates Related docs
fhir/igs/aggregate-minimal The smallest complete guide: the forms, one district, no category axis published Set up an IG project
fhir/igs/aggregate-disaggregated The same selection with both category axes on — the category pairs, the per-axis properties, and the ConceptMaps Terminology and ConceptMaps
fhir/igs/event-program A program without registration, and the two program rules that ride on its Questionnaire What goes in
fhir/igs/tracker-registration Registration, enrollment, two stage forms, and the person-only form the tracked entity type publishes The capture contract
fhir/igs/terminology-strict concept_code_source = "code" — concept codes taken from DHIS2 codes, and what that trades Generation
fhir/igs/registry-district One district as Organization and Location pairs, boundaries as GeoJSON, plus the organisation-unit code list What goes in
fhir/igs/facility-mixed The flagship: one of every capture kind at once, six Questionnaires in one guide The capture contract
fhir/igs/patient-summary The International Patient Summary end to end: who a person is, which recorded values are doses, the published section map, and the document $summary answers with What goes in
fhir/igs/refused-names The exhibit: a selection d2w fhir generate refuses, and the publisher failure it stands in for Troubleshooting

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 — d2w system whoami + d2w system info system
profile_list_verify.sh d2w 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
profile_session.sh Bind a profile to an existing browser login via --auth session + DHIS2_SESSION_COOKIE (plus optional DHIS2_SESSION_XSRF for CSRF-enforcing writes) auth
metadata_list.sh d2w metadata list — field presets, filters, order, --all metadata plugin
metadata_get.sh d2w metadata get <resource> <uid> — one object, narrowed by --fields metadata plugin
metadata_patch.sh RFC 6902 JSON Patch — inline --set / --remove and file-based metadata plugin
metadata_export.sh d2w metadata export — a narrow slice and the full catalog metadata plugin
metadata_import.sh d2w metadata import — dry run, the commit, and --strategy DELETE metadata plugin
metadata_export_filter.sh Per-resource filters + dangling-reference warning on export metadata plugin
metadata_diff.sh d2w metadata diff — bundle-vs-bundle or bundle-vs-live metadata plugin
metadata_search.sh Cross-resource UID / code / name search via d2w metadata search <query> metadata plugin
attribute_values.sh Cross-resource AttributeValue workflows via d2w metadata attributes metadata plugin
options.sh OptionSet + Option workflows — d2w metadata option-sets get / find / sync metadata plugin
legend_sets.sh d2w metadata legend-sets — create / get / clone / delete + the seeded LsDoseBand1 coverage dashboards legend sets API
organisation_units.sh d2w metadata organisation-units + groups + group-sets + levels — tree walk, per-level rename, group + dimension round-trip organisation units API
data_elements.sh d2w metadata data-elements + groups + group-sets — DE create, rename, legend-set attach, group + dimension round-trip data elements API
indicators.sh d2w metadata indicators + groups + group-sets — numerator/denominator expression pre-flight, create, group + dimension round-trip indicators API
program_indicators.sh d2w metadata program-indicators + groups — program-scoped expression validation + group membership (pair, no group-set) program indicators API
category_options.sh d2w metadata category-options + groups + group-sets — validity-window creation + group + dimension round-trip category options API
data_sets.sh d2w metadata data-sets + sections — DataSet create, DE attach (with per-set CC override), ordered Section round-trip data sets API
validation_rules.sh d2w metadata validation-rules + their groups — the authoring flip side of maintenance validation run validation rules + predictors API
predictors.sh d2w metadata predictors + their groups — the authoring flip side of maintenance predictors run validation rules + predictors API
tracker_schema.sh d2w 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 d2w metadata programs — tracker + event Program authoring with PTEA enrollment form + OU scoping tracker schema API
tracker_program_stages.sh d2w metadata program-stages — stage authoring with ordered PSDE list + reorder + per-DE compulsory flag tracker schema API
messaging.sh d2w messaging send / get / reply / set-priority / assign / delete — ticket-workflow round-trip messaging plugin
program_rules.sh d2w metadata program-rules — vars, validate-expression, where-de-is-used metadata plugin
sql_views.sh d2w metadata list sqlViews / 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 d2w user — list / get / invite / reinvite / reset-password user plugin
user_groups.sh d2w user group admin workflows user groups + roles
user_roles.sh d2w user role admin workflows user groups + roles
security.sh d2w security settings — read-only security posture (password policy, registration, lockout) CLI reference
schema.sh d2w schema <type> — describe a generated type's fields (offline; reflects the active version tree) CLI reference
route_register_and_run.sh d2w route lifecycle across every upstream auth type auth schemes
customize_login.sh Brand the DHIS2 login page + top menu customize plugin
doctor.sh d2w doctor — probe every BUGS.md gotcha + metadata-health check doctor plugin
maintenance.sh d2w maintenance — background tasks, cache, cleanup, integrity maintenance plugin
files.sh d2w files — documents (URL + binary round-trip) + fileResource (MESSAGE_ATTACHMENT round-trip) files plugin
visualizations.sh d2w metadata visualizations + d2w metadata dashboards — flag-driven viz create, clone, dashboard compose visualizations guide
visualization_screenshot.sh d2w browser viz screenshot — PNG capture via the Data Visualizer app (needs [browser] extra) visualizations guide
maps.sh d2w metadata maps — thematic choropleth authoring via REST maps API
map_screenshot.sh d2w browser map screenshot — PNG capture via the Maps app (needs [browser] extra) maps API
apps.sh d2w apps list / hub-list / hub-url / update --dry-run / update --all / reload over /api/apps + /api/appHub apps API
dev_codegen.sh d2w dev codegen — regenerate the typed client from a live instance codegen
profile_pat.sh d2w profile pat create — provision a PAT as admin auth
dev_sample.sh d2w dev sample ... — inject fixtures + verify end-to-end manual testing
dev_uid.sh d2w dev uid — mint 11-char DHIS2 UIDs client-side, offline CLI reference

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 CookbookRetryPolicy for transient 5xx / connection errors on batch workflows client library tutorial
task_await.py Cookbookclient.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 Cookbookclient.maintenance.iter_integrity_issues streams tagged issues, severity histogram, early-break scan maintenance plugin
system_cache.py Cookbookclient.system cache: info() primed on connect, default_category_combo_uid(), per-key setting(), invalidate + refetch system API
files_documents.py Cookbookclient.files documents + fileResource round-trip; external URL docs, binary two-step upload, MESSAGE_ATTACHMENT round-trip files plugin
bulk_delete.py Cookbookclient.metadata.delete_bulk / delete_bulk_multi for one-call teardown via /api/metadata?importStrategy=DELETE metadata accessor
metadata_patch_bulk.py Cookbookclient.metadata.patch_bulk fans out RFC 6902 patches across many UIDs with per-UID failure capture metadata accessor
bulk_save.py Cookbookclient.resources.<res>.save_bulk(items) writes a typed list of one resource in one call metadata accessor
metadata_dry_run.py Cookbookclient.metadata.dry_run(...) as the pre-commit gate, and the refusal read back off the Dhis2ApiError metadata accessor
stream_data_values.py Cookbookclient.data_values.stream four ways: bytes, sync generator, Path (CSV), 1000-row file with timing data values streaming
stream_analytics.py Cookbookclient.analytics.stream_to for JSON / CSV / rawData exports to disk with per-format timing analytics streaming
data_values_export.py Cookbookclient.data_values.export as a typed DataValueSet, then client.stream of the same export to a Path, a BytesIO, and a chunk callable data values
data_values_import_atomic.py Cookbook — the same partly invalid payload imported under atomic_mode="ALL" and "OBJECT", reading the summary from a 200 or a 409 alike data values
complete_data_set_registrations_read.py Cookbookclient.complete_data_set_registrations.export lists which forms are reported complete below the root over a date range aggregate
tracker_reads.py Cookbookclient.tracker.tracked_entities / enrollments / events page through one program's records with typed row parsing tracker reads
analytics_event_query.py Cookbookclient.analytics.event_query / enrollment_query line lists for the seeded Child Programme analytics streaming
analytics_tables_poll_once.py Cookbookclient.maintenance.run_analytics_tables followed with client.tasks.poll_once, one poll per tick with a carried cursor tasks module
messaging_with_attachment.py Cookbookclient.messaging.send + MESSAGE_ATTACHMENT fileResource pairing; full inbox lifecycle (list, reply, mark-read, delete) messaging plugin
validation_rules.py Cookbookclient.validation workflow: expression validation, run analysis, list persisted results validation API
predictors.py Cookbookclient.predictors.run_all over a date range with import-count envelope 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
dashboard_item_users.py DashboardItem.user -> users (rename + reshape) schema diff v41 -> v42 -> v43 / versioning
tracked_entity_attribute_favorites.py TrackedEntityAttribute.favorite -> favorites + 6 new search fields schema diff v41 -> v42 -> v43
program_set_labels.py v43-only — client.programs.set_labels overrides enrollmentsLabel / eventsLabel / programStagesLabel schema diff v41 -> v42 -> v43
program_set_change_log.py v43-only — toggle Program.enableChangeLog (server-side enrollment + event audit) schema diff v41 -> v42 -> v43
program_set_enrollment_category_combo.py v43-only — set the alt enrollmentCategoryCombo reference applied at enrollment time schema diff v41 -> v42 -> v43
event_visualization_fix_headers.py EventChart / EventReport / EventVisualization add fixColumnHeaders / fixRowHeaders / hideEmptyColumns schema diff v41 -> v42 -> v43
map_basemaps.py Map.basemaps v43-only addition + new Basemap model schema diff v41 -> v42 -> v43
section_user_removed.py Section.user removed in v43 (also Section.favorite) schema diff v41 -> v42 -> v43
removed_resources.py pushAnalysis / externalFileResource / dataInputPeriods removed in v43 schema diff v41 -> v42 -> v43
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.py service.export_metadata — a typed MetadataBundle, walked and narrowed by per-resource filters metadata plugin
metadata_diff.py service.diff_bundles + diff_bundle_against_instance metadata plugin
metadata_bulk_import.py service.import_metadata — a typed bundle pushed, dry run then committed 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.py client.validation_rules + its groups — CRUD round-trip + group membership validation rules + predictors API
predictors.py client.predictors + its 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.py User groups via the Python client user groups + roles
user_roles.py 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_table.py PIVOT_TABLE — organisation units down the side, periods across the top visualizations guide
viz_single_value.py SINGLE_VALUE — the KPI tile, and why its grid collapses to one cell 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_list.py metadata_type_list + metadata_list — what an instance holds, paged and filtered metadata plugin
metadata_get.py metadata_get — one object by UID, whole or narrowed by fields 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.py metadata_export — a bundle written to disk, the summary answered back, dangling references named metadata plugin
metadata_import.py metadata_import — the dry run an agent should ask for first, then the commit 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.py metadata_validation_rule_* (plus groups) — CRUD round-trip via MCP validation rules + predictors API
predictors.py 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
user_groups.py User groups + their sharing block via MCP (user_group_list, user_group_sharing_get) user groups + roles
user_roles.py User roles + their authorities via MCP (user_role_list, user_role_authority_list) 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.

Running the whole set

make verify-examples runs every example on this page against the active profile and prints a per-surface PASS / FAIL / TIMEOUT / SKIP table. Three things decide what a batch pass actually executes:

  • Skipped by default. An example that needs Chromium, a human-clicked login, public-internet egress, or a dockerized SUSHI compile carries a stated reason in SKIP_BY_DEFAULT in infra/scripts/verify_examples.py. --include-browser opts the UI-driven set back in.
  • Skipped when the environment is missing. An example that reads a real secret or endpoint out of the environment - a personal access token, a caller's own DHIS2 credentials - runs when every variable it names is set and skips naming the missing ones otherwise. An unprovisioned machine is a fact about the machine, not a defect in the example, and make verify-examples sources infra/home/credentials/.env.auth first so a seeded checkout provides them all.
  • One shared FHIR fixture. Every examples/fhir/client/ example stands up what it needs through client/_fixture.py - a scaffolded project, a translation context built live off the instance, and a d2w fhir serve --live facade on a port the operating system picks. Run one by hand and it builds its own; run the suite and the suite builds one before its loop, exports D2W_FHIR_EXAMPLE_PROJECT and D2W_FHIR_EXAMPLE_FACADE, and stops the facade after the last example, so a batch pass boots one server instead of a dozen. Set either variable yourself and the suite leaves your fixture alone. The two examples about authentication still start a guarded facade apiece: the facade seam answers the open default posture only, and a shared open server cannot show what a token or dhis2 posture changes.

make refresh-and-verify is the full cycle: rebuild the seeded stack, seed the tokens, refresh the analytics tables the analytics examples read, then run the suite.

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 plugin group has representative examples. The 40-ish v42 MCP scripts can't cover all ~304 tools 1:1, but each plugin group (metadata_*, analytics_*, data_*, apps_*, ...) gets at least one runnable example showing the expected input shape + how to unpack the structured_content return.

When adding a new plugin / command / MCP tool: update this file alongside the feature PR so the catalogue stays in sync.