Send data to DHIS2 instance from R

Dear Community,

I am new to DHIS2 and my objective is quite specific. We have a Project Management System based on DHIS2, where data is entered manually. Knowing that DHIS2 has an API, could I be pointed towards how I can use the API to send data to Data Entry forms in DHIS2 via R?

1 Like

Dear @Tumaini_Kilimba,

I think this guideline and script will be useful: https://dhis2trainingland.com/eportal/wp-content/uploads/expert-academy-2018/Scripting_in_Multiple_Languages.pdf

Linking DHIS2 to an external web portal using DHIS2 Web API and R

#Linking DHIS2 to an external web portal using DHIS2 Web API – DHIS2 Web Portal

Script:

dhis.json file:
{
“dhis”: {
“baseurl”: “https://server-url”,
“username”: “username”,
“password”: “password”
},
“database”: {
“host”: “localhost”,
“port”: 5432,
“username”: “username”,
“password”: “password”,
“dbname”: “dhis2”
}
}

#!/usr/bin/env Rscript
modifyDataStore.R, an R script by Jason Pickering loosely based on a script by Ben Guaraldi (and lightly edited by same)

require(httr)
require(rlist)
require(jsonlite)
require(magrittr)
require(assertthat)

Get parameters from dish.json

config ← fromJSON(‘/opt/dhis2/dish.json’)
url<-paste0(config$dhis$baseurl, ‘/api/dataStore/assignments/organisationUnitLevels.json’)

Get the current JSON from the organisationUnitLevels key of the assignments namespace in the data store

j <-GET(url, authenticate(config$dhis$username, config$dhis$password)) %>%
content(., “text”) %>%
fromJSON(.)

Construct a new JSON from the current JSON, adding a new key and resorting it

j$Pirate ← j$Zimbabwe
j$Pirate$name3 ← ‘Pirate’
j ← j[order(names(j))]

Replace the old JSON with the new JSON

r ← PUT(url, body = toJSON(j, auto_unbox = TRUE), content_type_json())

Report completion
message(‘Exiting normally’)

Credit: Ben Guaraldi, Technical Lead for DATIM

Julhas

3 Likes

Yes, you can use the DHIS2 API to send data to data Entry forms in DHIS2 using R. DHIS2 provides a RESRful API that allows you to interact with the system programmatically.

  1. Authenticate with DHIS2 API using R libraries like httr.
  2. Identify the Data Entry form details, including form ID, organization unit, and period.
  3. Format data in the appropriate DHIS2 data model format (e.g., JSON or XML).
  4. Send HTTP POST request to DHIS2 API with the formatted data using R libraries.
  5. Check response status to confirm successful submission. Refer to DHIS2 API documentation for details.
2 Likes

Hi @Tumaini_Kilimba

As mentioned by Julhas and Arjun above, you can use the DHIS2 API to log into DHIS2 and POST data element values to a data set.

The method outlined by Arjun is correct. I would like to add a couple additional resources and comments.

  • The POST request to api/dataValueSets endpoint also accepts payloads in CSV format. This may be easier to prepare than JSON or XML, even though you cannot GET values in CSV format. More information on that, including the CSV template, is located in the developer guide here.
  • The developer guide also includes resources on using DHIS2 with R, located here, including the datimutils package developed by PEPFAR. This package doesnt include functions to POST data, but are helpful wrappers for extracting data and metadata from the DHIS2 API.
  • While many tutorials have a variable to hardcode your credentials in an R script, this is not a good idea for production systems. It might be a good idea to set your password with a separate auth.json file, or check the keyring R package to access your system credentials store

Here is a simple example

library(httr)
library(readr)
library(assertthat)
library(jsonlite)
library(purrr)

baseurl<-"https://play.dhis2.org/2.38nightly/"
username<-"admin"
password<-"district"

loginDHIS2<-function(baseurl,username,password) {
  url<-paste0(baseurl,"api/me")
  r<-GET(url,authenticate(username,password))
  assert_that(r$status_code == 200L) }

loginDHIS2(baseurl,username,password)

# get dataset
dataSet<-"BfMAe6Itzgt"
period<-"202101"
ou<-"DiszpKrYNg8"

url<-paste0(baseurl,
            "api/dataValueSets.json?",
            "dataSet=", dataSet,
            "&period=",period,
            "&orgUnit=",ou)

output<-fromJSON(content(GET(url),type="text", encoding="UTF-8"))

# output
head(output$dataValues) #note that "dataValues" object is in tabular format with data

# now select and update a data value within output
purrr::pluck(output,"dataValues","value",1)<-103

# head(output$dataValues)
# double check its updated

#POST back to server

resp<-httr::POST(url,body=toJSON(output), content_type_json())

resp$status_code #check 200 response

Thank you all for your responses. @brian is there a sandbox where I can test out these ideas without installing a local version of DHIS2?

for example I want to enter data for the following facility and that particular data set HIV Pediatric monthly summary on the play server DHIS 2 Demo - Sierra Leone, how would I go about it?

Where do I get these values? How do I look them up?

image

Hi @Tumaini_Kilimba ,

dataSet and ou are the UIDs of the data set and organization unit, respectively, for which you want to extract or post data.

You can find these UIDs with two metadata queries

/api/dataSets?filter=name:ilike:HIV
/api/organisationUnits?filter=name:ilike:Bandasuma

I suggest you explore the API documentation for more detailed examples in the developer guide. Metadata - DHIS2 Documentation

Alternatively, in the Maintenance app you could click the menu to the right of the dataSet or organization unit, and then SEE DETAILS

Another trick is to open metadata object (Organisation Unit or Data Set) in the Maintenance App. The 11 character UID for the object is at the end of the URL, as highlighted here

1 Like

Thank you , I will try this out.

2 Likes

Hi, I found this discussion helpful but I failed to use POST or PUT to create/update data in my DHIS2 instance.
While using POST, the response is 200 but the data is not updated…and it would return 401 or 405 when using PUT…

Also, I have to put the api version in the url, is it normal?
url2<-“https://base.rul/api/29/dataValueSets.json?dataSet=@@@@&period=2024&orgUnit=@@@@

resp<-httr::PUT(url2,body=jsonlite::toJSON(output,auto_unbox = TRUE), httr::content_type_json(), httr::authenticate(user=“####”, password =“####”))

Hi @kateshih

In your request URL, could you remove the .json and try again? Thanks!