Everything you need to know about authenticating, querying data values, and pushing reports to DHIS2.
DHIS2's REST API is comprehensive, well-documented, and occasionally maddening. After integrating with DHIS2 deployments across 5 county health departments, here is the practical knowledge we wish we had from day one.
Authentication
DHIS2 supports three authentication methods: Basic auth (username:password base64 encoded) — fine for development, not for production. Personal Access Tokens (PAT) — available in DHIS2 2.38+, generated via My Profile > Personal access tokens and scoped to specific API operations. OAuth2 — for applications where end users authenticate with their own DHIS2 credentials.
For a server-to-server integration (e.g., your ETL pipeline pushing data to DHIS2), create a dedicated DHIS2 service account with minimum required permissions, generate a PAT, and use it with the Authorization: ApiToken header.
The Analytics API — for reading aggregate data
The Analytics API is the right choice for 90% of read use cases. It handles the organisation unit hierarchy, period logic and indicator calculations for you. Pass the dx (data element or indicator UIDs), pe (period identifiers such as LAST_12_MONTHS, 2024Q1, 202401), and ou (organisation unit UIDs) dimensions as query parameters.
The response is a JSON object with headers, rows, and metaData. Map UIDs to names using metaData.items.
The Data Value Sets API — for writing aggregate data
Use this when pushing aggregate data from an external system into DHIS2. POST to /api/dataValueSets with the dataSet UID, period, orgUnit and an array of dataValues. Always use dryRun: true in your first test call — it validates the payload without writing data.
The Tracker API — for individual-level data
If your DHIS2 deployment uses Tracker programs (case surveillance, patient tracking), use the Tracker API at /api/tracker/trackedEntities. The new Tracker API (DHIS2 2.36+) returns cleaner structures than the legacy trackedEntityInstances endpoint.
Organisation Unit Hierarchies
DHIS2 organisation units have levels (national → county → sub-county → facility) and each unit has a path. When querying the Analytics API, you can reference a specific unit, all level-4 units under a parent (using LEVEL-4), or the authenticated user's assigned org unit (using USER_ORGUNIT). Always cache the org unit tree locally — it changes rarely and fetching it per request is slow.
Period Identifiers
DHIS2 has its own period syntax: 202401 for January 2024 (monthly), 2024Q1 for Q1 2024 (quarterly), 2024 for a full calendar year, and LAST_12_MONTHS as a relative period. When using relative periods, always pass relativePeriodDate to anchor the period to a specific date — otherwise the result changes depending on when the query runs.
Common Errors
- 409 Conflict on Data Value Set imports: check for category option combo mismatches. The categoryOptionCombo defaults to 'default' but some data sets require explicit combo UIDs.
- 403 Forbidden on Analytics: the service account user may lack 'View aggregate data' for the specific data set or org unit level.
- Slow Analytics queries: check if the analytics tables are up to date via /api/system/info → lastAnalyticsTableSuccess. Out-of-date analytics tables return stale data and run slowly.
