Overview

The Web API is a component which makes it possible for external systems to access and manipulate data stored in an instance of DHIS2. More precisely, it provides a programmatic interface to a wide range of exposed data and service methods for applications such as third-party software clients, web portals and internal DHIS2 modules.

Introduction

The Web API adheres to many of the principles behind the REST architectural style. To mention some important ones:

  1. The fundamental building blocks are referred to as resources. A resource can be anything exposed to the Web, from a document to a business process - anything a client might want to interact with. The information aspects of a resource can be retrieved or exchanged through resource representations. A representation is a view of a resource's state at any given time. For instance, the visualizations resource in DHIS2 represents visualizations of aggregated data for a certain set of parameters. This resource can be retrieved in a variety of representation formats including JSON and CSV.
  2. All resources can be uniquely identified by a URI (also referred to as URL). All resources have a default representation. You can indicate that you are interested in a specific representation by supplying an Accept HTTP header, a file extension or a format query parameter. So in order to retrieve a CSV representation of an analytics data response you can supply an Accept: application/csv header or append .csv or ?format=csv to your request URL.
  3. Interactions with the API requires the correct use of HTTP methods or verbs. This implies that for a resource you must issue a GET request when you want to retrieve it, POST request when you want to create one, PUT when you want to update it and DELETE when you want to remove it.

Authentication

The DHIS2 Web API supports three protocols for authentication:

Verify and get information about the currently authenticated user by making a GET request to the following endpoint.

Get the list of authorities for the currently authenticatd user.

GET /api/me/authorization

Check whether the currently authenticated user has the given authority.

GET /api/me/authorization/{authority}

For example, to check whether the user has the F_CONSTANT_ADD authority.

GET /api/me/authorization/F_CONSTANT_ADD

The response will be either true or false in JSON format.

Basic Authentication

The DHIS2 Web API supports Basic authentication. Basic authentication is a technique for clients to send login credentials over HTTP to a web server. Technically speaking, the username is appended with a colon and the password, Base64-encoded, prefixed Basic and supplied as the value of the Authorization HTTP header. More formally that is:

Authorization: Basic base64encode(username:password)

Most network-aware development environments provide support for Basic authentication, such as Apache HttpClient and Spring RestTemplate. An important note is that this authentication scheme provides no security since the username and password are sent in plain text and can be easily observed by an attacker. Using Basic is recommended only if the server is using SSL/TLS (HTTPS) to encrypt communication with clients. Consider this a hard requirement in order to provide secure interactions with the Web API.

Two-factor authentication

DHIS2 supports two-factor authentication. This can be enabled per user. When enabled, users will be asked to enter a 2FA code when logging in. You can read more about 2FA here.

Personal Access Token

Personal access tokens (PATs) are an alternative to using passwords for authentication to DHIS2 when using the API.

PATs can be a more secure alternative to HTTP Basic Authentication, and should be your preferred choice when creating a new app/script etc.

HTTP Basic Authentication is considered insecure because, among other things, it sends your username and password in clear text. It may be deprecated in future DHIS2 versions or made opt-in, meaning that basic authentication would need to be explicitly enabled in the configuration.

Important security concerns!

Your PATs will automatically inherit all the permissions and authorizations your user has. It is therefore extremely important that you limit the access granted to your token depending on how you intend to use it, see Configuring your token.

If you only want the token to have access to a narrow and specific part of the server, it is advised to rather create a new special user that you assign only the roles/authorities you want it to have access to.

Creating a token

To create a new PAT, you have two choices: * A. Create a token in the UI on your account's profile page. * B. Create a token via the API.

A. Creating a token on the account page

Log in with your username and password, go to your profile page (Click top right corner, and chose "Edit profile" from the dropdown). On your user profile page, choose "Personal access tokens" from the left side menu. You should now be on the "Manage personal access tokens" page and see the text: "You don't have any active personal access tokens". Click "Generate new token" to make a new token. A "Generate new token" popup will be shown and present you with two choices:

1. Server/script context

"This type is used for integrations and scripts that won't be accessed by a browser".

If you plan to use the token in an application, a script or similar, this type should be your choice.

2. Browser context

"This type us used for applications, like public portals, that will be accessed with a web browser".

If you need to link to DHIS2 on a webpage, or e.g. embed in an iframe, this is probably the type of token you want.

Configuring your token

After choosing what token type you want, you can configure different access constraints on your token. By constraint, we mean how to limit and narrow down how your token can be used. This can be of crucial importance if you plan on using the token in a public environment, e.g. on a public dashboard on another site, embedded in an iframe. Since tokens always have the same access/authorities that your user currently has, taking special care is needed if you intend to use it in any environment you don't have 100% control over.

NB: If anyone else gets their hands on your token, they can do anything your user can do. It is not possible to distinguish between actions performed using the token and other actions performed by your user.

Important: It is strongly advised that you create a separate unique user with only the roles/authorities you want the token to have if you plan on using PAT tokens in a non-secure and/or public environment, e.g. on a PC or server, you don't have 100% control over, or "embedded" in a webpage on another server.

Constraint types

  • Expiry time
  • Allowed UP addresses
  • Allowed HTTP methods
  • Allowed HTTP referrers
Expiry time

Expiry time simply sets for how long you want your token to be usable, the default is 30 days. After the expiry time, the token will simply return a 401 (Unauthorized) message. You can set any expiry time you want, but it is strongly advised that you set an expiry time that is reasonable for your use case.

IP addresses

This is a comma-separated list of IP addresses you want to limit where the token requests can come from.

Important: IP address validation relies on the X-Forwarded-For header, which can be spoofed. For security, make sure a load balancer or reverse proxy overwrites this header.

HTTP methods

A comma-separated list of HTTP methods you want your token to be able to use. If you only need your token to view data, not modify or delete, selecting only the GET HTTP method makes sense.

HTTP referrers

HTTP referer is a header added to the request, when you click on a link, this says which site/page you were on when you clicked the link. Read more about the HTTP referer header here: https://en.wikipedia.org/wiki/HTTP_referer

This can be used to limit the use of a "public" token embedded on another page on another site. Making sure that the referer header match the site hostname in should come from, can help avoid abuse of the token, e.g. if someone posts it on a public forum.

Important: this is not a security feature. The referer header can easily be spoofed. This setting is intended to discourage unauthorized third-party developers from connecting to public access instances.

Saving a token

When you are done configuring your token, you can save it by clicking the "Generate new token" button, on the bottom right of the pop-up. When doing so the token will be saved and a secret token key will be generated on the server. The new secret token key will be shown on the bottom of the PAT token list with a green background, and the text "Newly created token". The secret token key will look similar to this:

d2pat_5xVA12xyUbWNedQxy4ohH77WlxRGVvZZ1151814092
Important

: This generated secret token key will only be shown once, so it is important that you copy the token key now and save it in a secure place for use later. The secret token key will be securely hashed on the server, and only the hash of this secret token key will be saved to the database. This is done to minimize the security impact if someone gets unauthorized access to the database, similar to the way passwords are handled.

Creating a token with the API

Example of how to create a new Personal Access Token using the API:

POST /api/apiToken
Content-Type: application/json
Authorization: Basic admin district

{}
NB

: Remember the empty JSON body (

{}

) in the payload!

This will return a response containing a token similar to this:

{
  "httpStatus": "Created",
  "httpStatusCode": 201,
  "status": "OK",
  "response": {
     "responseType": "ApiTokenCreationResponse",
     "key": "d2pat_5xVA12xyUbWNedQxy4ohH77WlxRGVvZZ1151814092",
     "uid": "jJYrtIVP7qU",
     "klass": "org.hisp.dhis.security.apikey.ApiToken",
     "errorReports": []
  }
}

Note: The token key will only be shown once here in this response. You need to copy and save this is in a secure place for use later!

The token itself consists of three parts: 1. Prefix: (d2pat_) indicates what type of token this is. 2. Random bytes Base64 encoded: (5xVA12xyUbWNedQxy4ohH77WlxRGVvZZ) 3. CRC32 checksum: (1151814092) the checksum part is padded with 0 so that it always stays ten characters long.

Configure token with the API

To change any of the constraints on your token, you can issue the following HTTP API request.

Note: Only the constraints are possible to modify after the token has been created.

PUT /api/apiToken/jJYrtIVP7qU
Content-Type: application/json
Authorization: Basic admin district
{
  "version": 1,
  "type": "PERSONAL_ACCESS_TOKEN",
  "expire": 163465349603200,
  "attributes": [
      {
        "type": "IpAllowedList",
        "allowedIps": ["192.168.0.1"]
      },
      {
        "type": "MethodAllowedList",
        "allowedMethods": ["GET"]
      }
  ]
}

Using a Personal Access Token

To issue a request with your newly created token, use the Authorization header accordingly. The authorization header format is:

Authorization: ApiToken [YOUR_SECRET_API_TOKEN_KEY]

For example:

GET /api/apiToken/jJYrtIVP7qU
Content-Type: application/json
Authorization: ApiToken d2pat_5xVA12xyUbWNedQxy4ohH77WlxRGVvZZ1151814092

Deleting a Personal Access Token

You can delete your PATs either in the UI on your profile page where you created it, or via the API like this:

DELETE /api/apiToken/jJYrtIVP7qU
Content-Type: application/json
Authorization: ApiToken d2pat_5xVA12xyUbWNedQxy4ohH77WlxRGVvZZ1151814092

OAuth2

DHIS2 supports the OAuth2 authentication protocol. OAuth2 is an open standard for authorization which allows third-party clients to connect on behalf of a DHIS2 user and get a reusable bearer token for subsequent requests to the Web API. DHIS2 does not support fine-grained OAuth2 roles but rather provides applications access based on user roles of the DHIS2 user.

Each client for which you want to allow OAuth 2 authentication must be registered in DHIS2. To add a new OAuth2 client go to Apps > Settings > OAuth2 Clients in the user interface, click Add new and enter the desired client name and the grant types.

Create a Client

An OAuth2 client can be added through the Web API. As an example, we can send a payload like this:

{
  "name": "OAuth2 Demo Client",
  "cid": "demo",
  "secret": "1e6db50c-0fee-11e5-98d0-3c15c2c6caf6",
  "grantTypes": [
    "password",
    "refresh_token",
    "authorization_code"
  ],
  "redirectUris": [
    "http://www.example.org"
  ]
}

The payload can be sent with the following command:

SERVER="https://play.dhis2.org/dev"
curl -X POST -H "Content-Type: application/json" -d @client.json
  -u admin:district "$SERVER/api/oAuth2Clients"

This client will be used as the basis for the next grant type examples.

Grant type password

The simplest of all grant types is the password grant type. This grant type is similar to basic authentication in the sense that it requires the client to collect the user's username and password. As an example we can use our demo server:

SERVER="https://play.dhis2.org/dev"
SECRET="1e6db50c-0fee-11e5-98d0-3c15c2c6caf6"

curl -X POST -H "Accept: application/json" -u demo:$SECRET "$SERVER/uaa/oauth/token"
  -d grant_type=password -d username=admin -d password=district

This will give you a response similar to this:

{
  "expires_in": 43175,
  "scope": "ALL",
  "access_token": "07fc551c-806c-41a4-9a8c-10658bd15435",
  "refresh_token": "a4e4de45-4743-481d-9345-2cfe34732fcc",
  "token_type": "bearer"
}

For now, we will concentrate on the access_token, which is what we will use as our authentication (bearer) token. As an example, we will get all data elements using our token:

SERVER="https://play.dhis2.org/dev"
curl -H "Authorization: Bearer 07fc551c-806c-41a4-9a8c-10658bd15435" "$SERVER/api/33/dataElements.json"

Grant type refresh_token

In general the access tokens have limited validity. You can have a look at the expires_in property of the response in the previous example to understand when a token expires. To get a fresh access_token you can make another round trip to the server and use refresh_token which allows you to get an updated token without needing to ask for the user credentials one more time.

SERVER="https://play.dhis2.org/dev"
SECRET="1e6db50c-0fee-11e5-98d0-3c15c2c6caf6"
REFRESH_TOKEN="a4e4de45-4743-481d-9345-2cfe34732fcc"

curl -X POST -H "Accept: application/json" -u demo:$SECRET "$SERVER/uaa/oauth/token"
  -d "grant_type=refresh_token" -d "refresh_token=$REFRESH_TOKEN"

The response will be exactly the same as when you get a token to start with.

Grant type authorization_code

Authorized code grant type is the recommended approach if you don't want to store the user credentials externally. It allows DHIS2 to collect the username/password directly from the user instead of the client collecting them and then authenticating on behalf of the user. Please be aware that this approach uses the redirectUris part of the client payload.

Step 1: Visit the following URL using a web browser. If you have more than one redirect URIs, you might want to add &redirect_uri=http://www.example.org to the URL:

SERVER="https://play.dhis2.org/dev"
$SERVER/uaa/oauth/authorize?client_id=demo&response_type=code

Step 2: After the user has successfully logged in and accepted your client access, it will redirect back to your redirect uri like this:

http://www.example.org/?code=XYZ

Step 3: This step is similar to what we did in the password grant type, using the given code, we will now ask for an access token:

SERVER="https://play.dhis2.org/dev"
SECRET="1e6db50c-0fee-11e5-98d0-3c15c2c6caf6"

curl -X POST -u demo:$SECRET -H "Accept: application/json" $SERVER/uaa/oauth/token
-d "grant_type=authorization_code" -d "code=XYZ"

Error and info messages

The Web API uses a consistent format for all error/warning and informational messages:

{
  "httpStatus": "Forbidden",
  "message": "You don't have the proper permissions to read objects of this type.",
  "httpStatusCode": 403,
  "status": "ERROR"
}

Here we can see from the message that the user tried to access a resource I did not have access to. It uses the http status code 403, the HTTP status message forbidden and a descriptive message.

WebMessage properties
Name Description
httpStatus HTTP Status message for this response, see RFC 2616 (Section 10) for more information.
httpStatusCode HTTP Status code for this response, see RFC 2616 (Section 10) for more information.
status DHIS2 status, possible values are OK | WARNING | ERROR, where OK means everything was successful, ERROR means that operation did not complete and WARNING means the operation was partially successful, if the message contains a response property, please look there for more information.
message A user-friendly message telling whether the operation was a success or not.
devMessage A more technical, developer-friendly message (not currently in use).
response Extension point for future extensions of the WebMessage format.

Date and period format

Throughout the Web API, we refer to dates and periods. The date format is:

For example, if you want to express March 20, 2014, you must use 2014-03-20.

The period format is described in the following table (also available on the API endpoint /api/periodTypes)

Period format
Interval Format Example Description
Day yyyyMMdd 20040315 March 15, 2004
Week yyyyWn 2004W10 Week 10 2004
Week Wednesday yyyyWedWn 2015WedW5 Week 5 with start Wednesday
Week Thursday yyyyThuWn 2015ThuW6 Week 6 with start Thursday
Week Saturday yyyySatWn 2015SatW7 Week 7 with start Saturday
Week Sunday yyyySunWn 2015SunW8 Week 8 with start Sunday
Bi-week yyyyBiWn 2015BiW1 Week 1-2 20015
Month yyyyMM 200403 March 2004
Bi-month yyyyMMB 200401B January-February 2004
Quarter yyyyQn 2004Q1 January-March 2004
Six-month yyyySn 2004S1 January-June 2004
Six-month April yyyyAprilSn 2004AprilS1 April-September 2004
Year yyyy 2004 2004
Financial Year April yyyyApril 2004April Apr 2004-Mar 2005
Financial Year July yyyyJuly 2004July July 2004-June 2005
Financial Year Oct yyyyOct 2004Oct Oct 2004-Sep 2005

Relative Periods

In some parts of the API, like for the analytics resource, you can utilize relative periods in addition to fixed periods (defined above). The relative periods are relative to the current date and allow e.g. for creating dynamic reports. The available relative period values are described in the table below.

Name Keyword
Today TODAY
Yesterday YESTERDAY
Last 3 days LAST_3_DAYS
Last 7 days LAST_7_DAYS
Last 14 days LAST_14_DAYS
Last 30 days LAST_30_DAYS
Last 60 days LAST_60_DAYS
Last 90 days LAST_90_DAYS
Last 180 days LAST_180_DAYS
This month THIS_MONTH
This bi-month THIS_BIMONTH
Last bi-month LAST_BIMONTH
This quarter THIS_QUARTER
Last quarter LAST_QUARTER
This six-month THIS_SIX_MONTH
Last six-month LAST_SIX_MONTH
Weeks this year WEEKS_THIS_YEAR
Months this year MONTHS_THIS_YEAR
Bi-months this year BIMONTHS_THIS_YEAR
Quarters this year QUARTERS_THIS_YEAR
This year THIS_YEAR
Months last year MONTHS_LAST_YEAR
Quarters last year QUARTERS_LAST_YEAR
Last year LAST_YEAR
Last 5 years LAST_5_YEARS
Last 10 years LAST_10_YEARS
Last 12 months LAST_12_MONTHS
Last 6 months LAST_6_MONTHS
Last 3 months LAST_3_MONTHS
Last 6 bi-months LAST_6_BIMONTHS
Last 4 quarters LAST_4_QUARTERS
Last 2 six-months LAST_2_SIXMONTHS
This financial year THIS_FINANCIAL_YEAR
Last financial year LAST_FINANCIAL_YEAR
Last 5 financial years LAST_5_FINANCIAL_YEARS
Last 10 financial years LAST_10_FINANCIAL_YEARS
This week THIS_WEEK
Last week LAST_WEEK
This bi-week THIS_BIWEEK
Last bi-week LAST_BIWEEK
Last 4 weeks LAST_4_WEEKS
Last 4 bi-weeks LAST_4_BIWEEKS
Last 12 weeks LAST_12_WEEKS
Last 52 weeks LAST_52_WEEKS

It is possible retrieve the ISO representations of these relative periods by making a GET request to the /api/relativePeriods/{RELATIVE_PERIOD_KEYWORD}

The endpoint supports the following parameters: - startDate: Represents the start date to calculate the relative period from. Format: yyyy-MM-dd. Default is today if not provided. - financialYearStart: Should be one of FINANCIAL_YEAR_APRIL, FINANCIAL_YEAR_JULY, FINANCIAL_YEAR_OCTOBER. Default is FINANCIAL_YEAR_OCTOBER if not provided.

As an example, to get the ISO representation of the relative period LAST_3_MONTHS from the date 2021-08-15, you can issue the following request: GET /api/relativePeriods/LAST_3_MONTHS?startDate=2021-08-15

The response in this case would be:

{
[
"202105",
"202106",
"202107"
]
}

Custom date periods

Analytics query resources support extra parameters to express periods.

Default pe dimension will fall back to:

  • eventDate for /analytics/events/query
  • enrollmentDate for /analytics/enrollments/query

Adding conditions on one or more date fields and combining them are allowed.

Usage of custom date periods

In resources supporting custom date periods, there are extra query parameters that will be combined to express conditions on the time dimension.

custom date period events query resource enrollment query resource
eventDate [x] [ ]
enrollmentDate [x] [x]
scheduledDate [x] [ ]
incidentDate [x] [x]
lastUpdated [x] [x]

Conditions can be expressed in the following format:

/api/analytics/events/query/...?...&eventDate=2021&...

It's possible to combine more time fields in the same query:

/api/analytics/events/query/...?...&eventDate=2021&incidentDate=202102&...

All of these conditions can be combined with pe dimension:

/api/analytics/events/query/...?...&dimension=pe:TODAY&enrollmentDate=2021&incidentDate=202102&...

Supported formats are described in "date and period format" above. An extra format is provided to express a range of dates: yyyyMMdd_yyyyMMdd and yyyy-MM-dd_yyyy-MM-dd.

In the example bellow, the endpoint will return events that are scheduled to happen between 20210101 and 20210104:

/api/analytics/events/query/...?...&dimension=pe:TODAY&enrollmentDate=2021&incidentDate=202102&scheduledDate=20210101_20210104&...

Authorities

All available system authorities can be listed with identifiers and names using the following endpoint.

It returns the following format:

{
  "systemAuthorities": [
    {
      "id": "ALL",
      "name": "ALL"
    },
    {
      "id": "F_ACCEPT_DATA_LOWER_LEVELS",
      "name": "Accept data at lower levels"
    }
  ]
}