انتقل إلى المحتوى
For the complete DHIS2 documentation index, see llms.txt.

Metadata

Identifier schemes

This section provides an explanation of the identifier scheme concept. Identifier schemes are used to map metadata objects to other metadata during import, and to render metadata as part of exports. Note that not all schemes work for all API calls, and not all schemes can be used for both input and output. This is outlined in the sections explaining the various API endpoints.

The full set of identifier scheme object types available are listed below, using the name of the property to use in queries:

  • idScheme
  • dataElementIdScheme
  • categoryOptionComboIdScheme
  • orgUnitIdScheme
  • programIdScheme
  • programStageIdScheme
  • trackedEntityIdScheme
  • trackedEntityAttributeIdScheme

The general idScheme applies to all types of objects. It can be overridden by specific object types.

The default scheme for all parameters is UID (stable DHIS2 identifiers). The supported identifier schemes are described in the table below.

Scheme Values
Scheme Description
ID, UID Match on DHIS2 stable Identifier, this is the default id scheme.
CODE Match on DHIS2 Code, mainly used to exchange data with an external system.
NAME Match on DHIS2 Name, please note that this uses what is available as object.name, and not the translated name. Also note that names are not always unique, and in that case, they can not be used.
ATTRIBUTE:ID Match on metadata attribute, this attribute needs to be assigned to the type you are matching on, and also that the unique property is set to true. The main usage of this is also to exchange data with external systems, it has some advantages over CODE since multiple attributes can be added, so it can be used to synchronize with more than one system.

Note that identifier schemes is not an independent feature but needs to be used in combination with resources such as data value import, metadata import and GeoJson import.

As an example, to specify CODE as the general id scheme and override with UID for organisation unit id scheme you can use these query parameters:

?idScheme=CODE&orgUnitIdScheme=UID

As another example, to specify an attribute for the organisation unit id scheme, code for the data element id scheme and use the default UID id scheme for all other objects you can use these parameters:

?orgUnitIdScheme=ATTRIBUTE:j38fk2dKFsG&dataElementIdScheme=CODE

Browsing the Web API

The entry point for browsing the Web API is /api. This resource provides links to all available resources. Four resource representation formats are consistently available for all resources: HTML, XML, JSON, and JSONP. Some resources will have other formats available, like MS Excel, PDF, CSV, and PNG. To explore the API from a web browser, navigate to the /api entry point and follow the links to your desired resource, for instance /api/dataElements. For all resources which return a list of elements certain query parameters can be used to modify the response:

Query parameters
Parameter Option values Default option Description
paging true | false true Indicates whether to return lists of elements in pages.
page number 1 Defines which page number to return.
pageSize number 50 Defines the number of elements to return for each page.
order property:asc/iasc/desc/idesc Order the output using a specified order, only properties that are both persisted and simple (no collections, idObjects etc) are supported. iasc and idesc are case insensitive sorting. If it is wanted to sort for more than one property, separate them using a comma.

An example of how these parameters can be used to get a full list of data element groups in XML response format is:

/api/dataElementGroups.xml?links=false&paging=false

You can query for elements on the name property instead of returning a full list of elements using the query query variable. In this example we query for all data elements with the word "anaemia" in the name:

/api/dataElements?query=anaemia

You can get specific pages and page sizes of objects like this:

/api/dataElements.json?page=2&pageSize=20

You can completely disable paging like this:

/api/indicatorGroups.json?paging=false

To order the result based on a specific property:

/api/indicators.json?order=shortName:desc

To order the result based on created datetime property first (descending order) and then by name property (ascending order):

/api/indicators.json?order=created:desc,name:asc

You can find an object based on its ID across all object types through the identifiableObjects resource:

/api/identifiableObjects/<id>

Translation

DHIS2 supports translations of database content, such as data elements, indicators, and programs. All metadata objects in the Web API have properties meant to be used for display / UI purposes, which include displayName, displayShortName, displayDescription and displayFormName (for data elements and tracked entity attributes).

Translate options
Parameter Values Description
translate true | false Translate display* properties in metadata output (displayName, displayShortName, displayDescription, and displayFormName for data elements and tracked entity attributes). Default value is true.
locale Locale to use Translate metadata output using a specified locale (requires translate=true).

Translation API

The translations for an object is rendered as part of the object itself in the translations array. Note that the translations array in the JSON/XML payloads is normally pre-filtered for you, which means they can not directly be used to import/export translations (as that would normally overwrite locales other than current users).

Example of data element with translation array filtered on user locale:

{
  "id": "FTRrcoaog83",
  "displayName": "Accute French",
  "translations": [
    {
      "property": "SHORT_NAME",
      "locale": "fr",
      "value": "Accute French"
    },
    {
      "property": "NAME",
      "locale": "fr",
      "value": "Accute French"
    }
  ]
}

Example of data element with translations turned off:

{
  "id": "FTRrcoaog83",
  "displayName": "Accute Flaccid Paralysis (Deaths < 5 yrs)",
  "translations": [
    {
      "property": "FORM_NAME",
      "locale": "en_FK",
      "value": "aa"
    },
    {
      "property": "SHORT_NAME",
      "locale": "en_GB",
      "value": "Accute Flaccid Paral"
    },
    {
      "property": "SHORT_NAME",
      "locale": "fr",
      "value": "Accute French"
    },
    {
      "property": "NAME",
      "locale": "fr",
      "value": "Accute French"
    },
    {
      "property": "NAME",
      "locale": "en_FK",
      "value": "aa"
    },
    {
      "property": "DESCRIPTION",
      "locale": "en_FK",
      "value": "aa"
    }
  ]
}

Note that even if you get the unfiltered result, and are using the appropriate type endpoint i..e /api/dataElements we do not allow updates, as it would be too easy to make mistakes and overwrite the other available locales.

To read and update translations you can use the special translations endpoint for each object resource. These can be accessed by GET or PUT on the appropriate /api/<object-type>/<object-id>/translations endpoint.

As an example, for a data element with identifier FTRrcoaog83, you could use /api/dataElements/FTRrcoaog83/translations to get and update translations. The fields available are property with options NAME, SHORT_NAME, FORM_NAME, DESCRIPTION, locale which supports any valid locale ID and the translated property value.

Example of NAME property for French locale:

{
  "property": "NAME",
  "locale": "fr",
  "value": "Paralysie Flasque Aiguë (Décès <5 ans)"
}

This payload would then be added to a translation array, and sent back to the appropriate endpoint:

{
  "translations": [
    {
      "property": "NAME",
      "locale": "fr",
      "value": "Paralysie Flasque Aiguë (Décès <5 ans)"
    }
  ]
}

For a data element with ID FTRrcoaog83 you can PUT this to /api/dataElements/FTRrcoaog83/translations. Make sure to send all translations for the specific object and not just for a single locale (if not you will potentially overwrite existing locales for other locales).

The status code will be 204 No Content if the data value was successfully saved or updated, or 404 Not Found if there was a validation error (e.g. more than one SHORT_NAME for the same locale).

Web API versions

The Web API /api can be used with a DHIS2 version number, example:

/api/42/dataElements

Versions 28-43 are supported. Calling an endpoint with or without a version does not change the behaviour of the API. The behaviour is the same no matter which approach is used. We aim to remove supporting API calls with versions, so please use API calls without the use of a version number.
The support for using versions is due to legacy design, which didn't evolve as originally envisioned.

Metadata object filter

To filter the metadata there are several filter operations that can be applied to the returned list of metadata. The format of the filter itself is straight-forward and follows the pattern property:operator:value, where property is the property on the metadata you want to filter on, operator is the comparison operator you want to perform and value is the value to check against (not all operators require value).

Please see the schema section to discover which properties are available. In addition to the listed properties filters can apply to custom attribute values by using the attribute's ID as property name.

Recursive filtering, ie. filtering on associated objects or collection of objects, is supported as well.

Available Operators
Operator Types Value required Description
eq string | boolean | integer | float | enum | collection (checks for size) | date true Equality
!eq string | boolean | integer | float | enum | collection (checks for size) | date true Inequality
ieq string true Case insensitive string, match exact
ne string | boolean | integer | float | enum | collection (checks for size) | date true Inequality
like string true Case sensitive string, match anywhere
!like string true Case sensitive string, not match anywhere
$like string true Case sensitive string, match start
!$like string true Case sensitive string, not match start
like$ string true Case sensitive string, match end
!like$ string true Case sensitive string, not match end
ilike string true Case insensitive string, match anywhere
!ilike string true Case insensitive string, not match anywhere
$ilike string true Case insensitive string, match start
!$ilike string true Case insensitive string, not match start
ilike$ string true Case insensitive string, match end
!ilike$ string true Case insensitive string, not match end
gt string | boolean | integer | float | collection (checks for size) | date true Greater than
ge string | boolean | integer | float | collection (checks for size) | date true Greater than or equal
lt string | boolean | integer | float | collection (checks for size) | date true Less than
le string | boolean | integer | float | collection (checks for size) | date true Less than or equal
null all false Property is null
!null all false Property is not null
empty collection false Collection is empty
token string true Match on multiple tokens in search property
!token string true Not match on multiple tokens in search property
in string | boolean | integer | float | date true Find objects matching 1 or more values
!in string | boolean | integer | float | date true Find objects not matching 1 or more values

Operators will be applied as logical and query. If you need a or query, you can have a look at the in filter and the section below. The filtering mechanism allows for recursion. See below for some examples.

Get data elements with id property ID1 or ID2:

/api/dataElements?filter=id:eq:ID1&filter=id:eq:ID2

Get data elements, ignoring case, with name property MyDataElement:

/api/dataElements?filter=name:ieq:mydataelement

Get all data elements which have a data set with id ID1:

/api/dataElements?filter=dataSetElements.dataSet.id:eq:ID1

Get all data elements with aggregation operator sum and value type int:

/api/dataElements.json?filter=aggregationOperator:eq:sum&filter=type:eq:int

You can do filtering within collections, e.g. to get data elements which are members of the ANC data element group you can use the following query using the id property of the associated data element groups:

/api/dataElements.json?filter=dataElementGroups.id:eq:qfxEYY9xAl6

To get data elements with a particular attribute value for a metadata attribute, a filter for the attribute ID and the attribute value can be specified using the same collection query syntax:

/api/dataElements.json?filter=attributeValues.attribute.id:eq:n2xYlNbsfko&filter=attributeValues.value:eq:AFP

Get data elements which have any option set:

/api/dataElements?filter=optionSet:!null

Since all operators are and by default, you can't find a data element matching more than one id, for that purpose you can use the in operator.

/api/dataElements.json?filter=id:in:[fbfJHSPpUQD,cYeuwXTCPkU]

Logical operators

As mentioned in the section before, the default logical operator applied to the filters is AND which means that all object filters must be matched. There are however cases where you want to match on one of several filters (maybe id and code field) and in those cases, it is possible to switch the root logical operator from AND to OR using the rootJunction parameter.

Example: Normal filtering where both id and code must match to have a result returned

/api/dataElements.json?filter=id:in:[id1,id2]&filter=code:eq:code1

Example: Filtering where the logical operator has been switched to OR and now only one of the filters must match to have a result returned

/api/dataElements.json?filter=id:in:[id1,id2]&filter=code:eq:code1&rootJunction=OR

Identifiable token filter

In addition to the specific property based filtering mentioned above, we also have token based AND filtering across a set of properties: id, code, and name (also shortName if available). These properties are commonly referred to as identifiable. The idea is to filter metadata whose id, name, code or short name containing something.

Example: Filter all data elements containing 2nd in any of the following: id,name,code, shortName

/api/dataElements.json?filter=identifiable:token:2nd

It is also possible to specify multiple filtering values.

Example: Get all data elements where ANC visit is found in any of the identifiable properties. The system returns all data elements where both tokens (ANC and visit) are found anywhere in identifiable properties.

/api/dataElements.json?filter=identifiable:token:ANC visit

It is also possible to combine the identifiable filter with property-based filter and expect the rootJunction to be applied.

/api/dataElements.json?filter=identifiable:token:ANC visit&filter=displayName:ilike:tt1

/api/dataElements.json?filter=identifiable:token:ANC visit
  &filter=displayName:ilike:tt1&rootJunction=OR

Indexable only filter for tracked entity attributes

For tracked entity attributes, there is a special filter in addition to the previous mentioned filtering capabilities. Some of the tracked entity attributes are candidates for creating a trigram index for better lookup performance. Using the indexableOnly parameter set to true, the results can be filtered to include only the attributes that are trigram indexable.

Example: Get all tracked entity attributes that are indexable.

/api/trackedEntityAttributtes.json?indexableOnly=true

Additional filters along with the indexableOnly parameter can be specified.

Example: Get all tracked entity attributes where ANC is found in any of the name property. The system returns the tracked entity attributes where the name matches the provided keyword as well as if the attribute is indexable.

/api/trackedEntityAttributtes.json?filter=name:like:ANC&indexableOnly=true

Metadata field filter

In many situations, the default views of the metadata can be too verbose. A client might only need a few fields from each object and want to remove unnecessary fields from the response. To discover which fields are available for each object please see the schema section. In addition to the listed properties custom attributes can be included for top level objects by using the attribute's ID as property name.

The format for include/exclude allows for infinite recursion. To filter at the "root" level you can just use the name of the field, i.e. ?fields=id,name which would only display the id and name fields for every object. For objects that are either collections or complex objects with properties on their own, you can use the format ?fields=id,name,dataSets[id,name] which would return id, name of the root, and the id and name of every data set on that object. Negation can be done with the exclamation operator, and we have a set of presets of field select. Both XML and JSON formats are supported.

Example: Get id and name on the indicators resource:

/api/indicators?fields=id,name

Example: Get id and name from data elements, and id and name from the associated data sets:

/api/dataElements?fields=id,name,dataSets[id,name]

Example: Get id, name and the value of a user defined attribute with ID DnrLSdo4hMl for organisation units:

/api/organisationUnits?fields=id,name,DnrLSdo4hMl

The attribute is then included as property DnrLSdo4hMl of each matching object in the response. This can be renamed using the rename transformer as shown in the next section.

To exclude a field from the output you can use the exclamation ! operator. This is allowed anywhere in the query and will simply not include that property as it might have been inserted in some of the presets.

A few presets (selected fields groups) are available and can be applied using the : operator.

Property operators
Operator Description
<field-name> Include property with name, if it exists.
<object>[<field-name>, ...] Includes a field within either a collection (will be applied to every object in that collection), or just on a single object.
!<field-name>, <object>[!<field-name> Do not include this field name, it also works inside objects/collections. Useful when you use a preset to include fields.
*, <object>[*] Include all fields on a certain object, if applied to a collection, it will include all fields on all objects on that collection.
:<preset> Alias to select multiple fields. Three presets are currently available, see the table below for descriptions.
Field presets
Preset Description
all All fields of the object
* Alias for all
identifiable Includes id, name, code, created, lastUpdated and lastUpdatedBy fields
nameable Includes id, name, shortName, code, description, created and lastUpdated fields
persisted Returns all persisted property on an object, does not take into consideration if the object is the owner of the relation.
owner Returns all persisted property on an object where the object is the owner of all properties, this payload can be used to update through the API.

Example: Include all fields from data sets except organisation units:

/api/dataSets?fields=:all,!organisationUnits

Example: Include only id, name and the collection of organisation units from a data set, but exclude the id from organisation units:

/api/dataSets/BfMAe6Itzgt?fields=id,name,organisationUnits[:all,!id]

Example: Include nameable properties from all indicators:

/api/indicators.json?fields=:nameable

Field transformers

Field transforms can be used to transform properties. The syntax is described below.

/api/dataElements/ID?fields=id~rename(i),name~rename(n)

This will rename the id property to i and name property to n.

Multiple transformers can be applied to a single property by repeating the transformer operator:

/api/dataElementGroups.json?fields=id,displayName,dataElements~isNotEmpty~rename(haveDataElements)

The supported transformer operators are described in the table below.

Available Transformers
Name Arguments Description
size Gives sizes of strings (length) and collections
isEmpty Is string or collection empty
isNotEmpty Is string or collection not empty
rename Arg1: name Renames the property name
paging Arg1: page,Arg2: pageSize Pages a collection, default pageSize is 50.
pluck Optional Arg1: fieldName Converts an array of objects to an array of a selected field of that object. By default, the first field that is returned by the collection is used (normally the ID).
keyBy Optional Arg1: fieldName Converts an array of objects to an object where the fieldName (default id) is used as the key. This can be useful for quick lookups in JavaScript for example

Examples

Examples of transformer usage are found below.

Get the size of a collection:

/api/dataElements?fields=dataSets~size

Test if a collection is empty:

/api/dataElements?fields=dataSets~isEmpty

Test if a collection is not empty:

/api/dataElements?fields=dataSets~isNotEmpty

Rename properties:

/api/dataElements/ID?fields=id~rename(i),name~rename(n)

Apply paging to a collection:

/api/dataElementGroups?fields=id,displayName,dataElements~paging(1;20)

Get array with IDs of organisation units:

/api/categoryOptions.json?fields=id,organisationUnits~pluck

Get array with names of organisation units:

/api/categoryOptions.json?fields=id,organisationUnits~pluck[name]

Key the dataElements array by the id field:

/api/dataElementGroups.json?fields=id,name,dataElements~keyBy[id,name,valueType]

Key the dataElements array by the valueType field, since multiple hits this will results in arrays (of data elements):

/api/dataElementGroups.json?fields=id,name,dataElements~keyBy(valueType)[id,name,valueType]

Metadata create, read, update, delete, validate

All metadata entities in DHIS2 have their own API endpoint which supports CRUD operations (create, read, update and delete). The endpoint URLs follows this format:

/api/<entityName>

The entityName uses the camel-case notation. As an example, the endpoint for data elements is:

/api/dataElements

NOTE: When updating objects, all existing property values will be overwritten, even if the new value is null. Please use JSON Patch API in case you want do partial update to an object.

Create / update parameters

The following request query parameters are available across all metadata endpoints.

Available Query Filters
Param Type Required Options (default first) Description
preheatCache boolean false true | false Turn cache-map preheating on/off. This is on by default, turning this off will make initial load time for importer much shorter (but will make the import itself slower). This is mostly used for cases where you have a small XML/JSON file you want to import, and don't want to wait for cache-map preheating.
importStrategy enum false CREATE_AND_UPDATE | CREATE | UPDATE | DELETE Import strategy to use, see below for more information.

Creating and updating objects

For creating new objects you will need to know the endpoint, the type format, and make sure that you have the required authorities. As an example, we will create and update a constant. To figure out the format, we can use the new schema endpoint for getting format description. So we will start with getting that info:

http://<server>/api/schemas/constant.json

From the output, you can see that the required authorities for create are F_CONSTANT_ADD, and the important properties are: name and value. From this, we can create a JSON payload and save it as a file called constant.json:

{
  "name": "PI",
  "value": "3.14159265359"
}

The same content as an XML payload:

<constant name="PI" xmlns="http://dhis2.org/schema/dxf/2.0">
  <value>3.14159265359</value>
</constant>

We are now ready to create the new constant by sending a POST request to the constants endpoint with the JSON payload using curl:

curl -d @constant.json "http://server/api/constants" -X POST
  -H "Content-Type: application/json" -u user:password

A specific example of posting the constant to the demo server:

curl -d @constant.json "https://play.dhis2.org/api/constants" -X POST
  -H "Content-Type: application/json" -u admin:district

If everything went well, you should see an output similar to:

{
  "status": "SUCCESS",
  "importCount": {
    "imported": 1,
    "updated": 0,
    "ignored": 0,
    "deleted": 0
  },
  "type": "Constant"
}

The process will be exactly the same for updating, you make your changes to the JSON/XML payload, find out the ID of the constant, and then send a PUT request to the endpoint including ID:

curl -X PUT -d @pi.json -H "Content-Type: application/json"
  -u user:password "http://server/api/constants/ID"

Deleting objects

Deleting objects is very straight forward, you will need to know the ID and the endpoint of the type you want to delete, let's continue our example from the last section and use a constant. Let's assume that the id is abc123, then all you need to do is the send the DELETE request to the endpoint + id:

curl -X DELETE -u user:password "http://server/api/constants/ID"

A successful delete should return HTTP status 204 (no content).

Adding and removing objects in collections

The collections resource lets you modify collections of objects.

Adding or removing single objects

In order to add or remove objects to or from a collection of objects you can use the following pattern:

/api/{collection-object}/{collection-object-id}/{collection-name}/{object-id}

You should use the POST method to add, and the DELETE method to remove an object. When there is a many-to-many relationship between objects, you must first determine which object owns the relationship. If it isn't clear which object this is, try the call both ways to see which works.

The components of the pattern are:

  • collection object: The type of objects that owns the collection you want to modify.

  • collection object id: The identifier of the object that owns the collection you want to modify.

  • collection name: The name of the collection you want to modify.

  • object id: The identifier of the object you want to add or remove from the collection.

As an example, in order to remove a data element with identifier IDB from a data element group with identifier IDA you can do a DELETE request:

DELETE /api/dataElementGroups/IDA/dataElements/IDB

To add a category option with identifier IDB to a category with identifier IDA you can do a POST request:

POST /api/categories/IDA/categoryOptions/IDB

Adding or removing multiple objects

You can add or remove multiple objects from a collection in one request with a payload like this:

{
  "identifiableObjects": [{
      "id": "IDA"
    }, {
      "id": "IDB"
    }, {
      "id": "IDC"
    }
  ]
}

Using this payload you can add, replace or delete items:

Adding Items:

POST /api/categories/IDA/categoryOptions

Replacing Items:

PUT /api/categories/IDA/categoryOptions

Delete Items:

DELETE /api/categories/IDA/categoryOptions

Adding and removing objects in a single request

You can both add and remove objects from a collection in a single POST request to the following URL:

POST /api/categories/IDA/categoryOptions

The payload format is:

{
  "additions": [{
      "id": "IDA"
    }, {
      "id": "IDB"
    }, {
      "id": "IDC"
    }
  ],
  "deletions": [{
      "id": "IDD"
    }, {
      "id": "IDE"
    }, {
      "id": "IDF"
    }
  ]
}

Validating payloads

DHIS 2 supports system wide validation of metadata payloads, which means that create and update operations on the API endpoints will be checked for valid payload before allowing changes to be made. To find out what validations are in place for a specific endpoint, have a look at the /api/schemas endpoint, i.e. to figure out which constraints a data element have, you would go to /api/schemas/dataElement.

You can also validate your payload manually by sending it to the proper schema endpoint. If you wanted to validate the constant from the create section before, you would send it like this:

POST /api/schemas/constant

A simple (non-validating) example would be:

curl -X POST -d "{\"name\": \"some name\"}" -H "Content-Type: application/json"
  -u admin:district "https://play.dhis2.org/dev/api/schemas/dataElement"

Which will yield the result:

[
   {
      "message" : "Required property missing.",
      "property" : "type"
   },
   {
      "property" : "aggregationOperator",
      "message" : "Required property missing."
   },
   {
      "property" : "domainType",
      "message" : "Required property missing."
   },
   {
      "property" : "shortName",
      "message" : "Required property missing."
   }
]

Partial updates

For our API endpoints that deal with metadata, we support partial updates (PATCH) using the JSON patch standard. The payload basically outlines a set of operation you want applied to a existing metadata object. For JSON patch details and examples, see jsonpatch.com. Three operators are supported: add, remove and replace.

Below is a few examples relevant to DHIS2. Note that any update to a payload should be thought of as a HTTP PUT operation, i.e. any mutation must result in a valid PUT metadata payload.

The default importReportMode for JSON patch is ERRORS_NOT_OWNER which implies that when updating any property which is not owned by that particular object (for example trying to add a indicator group directly to an indicator) you will get an error.

As per the JSON patch specification you must always use the mimetype application/json-patch+json when sending patches.

Examples

Update name and value type of data element
PATCH /api/dataElements/{id}
[
  {"op": "add", "path": "/name", "value": "New Name"},
  {"op": "add", "path": "/valueType", "value": "INTEGER"}
] 
Add new data element to a data element group
PATCH /api/dataElementGroups/{id}
[
  {"op": "add", "path": "/dataElements/-", "value": {"id": "data-element-id"}}
]
Remove all data element associations from a data element group
PATCH /api/dataElementGroups/{id}
[
  {"op": "remove", "path": "/dataElements"}
]
Change domain and value type of a data element
PATCH /api/dataElements/{id}
[
    {"op": "add", "path": "/domainType", "value": "TRACKER"},
    {"op": "add", "path": "/valueType", "value": "INTEGER"}
]
Remove a specific orgUnit from an orgUnit group
PATCH /api/organisationUnitGroups/{id}
[
  {"op": "remove", "path": "/organisationUnits/1"}
]

Blocked add dataElementGroup to dataElement

PATCH /api/dataElements/{id}?importReportMode=ERRORS_NOT_OWNER
[
    {"op": "add", "path": "/dataElementGroups/-", "value": {"id": "data-element-group-id"}}
]

Blocked update name of dataElementGroup in dataElement

PATCH /api/dataElements/{id}?importReportMode=ERRORS_NOT_OWNER
[
    {"op": "add", "path": "/dataElementGroups/0", "value": {"name": "new-name"}}
]

Remove collection item by id

PATCH /api/dataSets/{id}?importReportMode=ERRORS_NOT_OWNER
[
    {"op": "remove-by-id", "path": "/organisationUnits", "id": "u6CvKyF0Db5"}
]

Patch request with invalid path

If path property is invalid or does not exist the patch service will return an error as below

PATCH /api/dataSets/{id}?importReportMode=ERRORS_NOT_OWNER

[
    {"op": "remove-by-id", "path": "/test", "id": "u6CvKyF0Db5"}
]
Response
{
    "httpStatus": "Bad Request",
    "httpStatusCode": 400,
    "status": "ERROR",
    "message": "Invalid path /test"
}

Metadata CSV export

Field filtering works almost the same for CSV (please note that using CSV on the /api/metadata endpoint is not supported), but not that field fransformations are not yet supported.

For endpoints that support CSV (our metadata endpoints like /api/dataElements /api/organisationUnits) you can either use the Accept header with value text/csv or you can use the extension .csv. Be aware that complex objects are not supported, and we only support id-object collections (so a list of UIDs will be returned).

Name خيارات Description
fields Same as metadata field filter (with the caveats mentioned above) Default filter is id,displayName
skipHeader false/true Should the header (with column names) be included or not
separator Default: . Column separator
arraySeparator Default: ; If one of the field is a collection of id-objects this separator will separate all the UIDs

Examples

Get all data elements including their group associations

/api/dataElements.csv?fields=id,displayName,dataElementGroups

Get all org units including geometry (which will get ignored)

/api/organisationUnits.csv?fields=id,displayName,organisationUnitGroups,geometry

Metadata export

This section explains the metatada API which is available at /api/metadata. XML and JSON resource representations are supported.

/api/metadata

The most common parameters are described below in the "Export Parameter" table. You can also apply this to all available types by using type:fields=<filter> and type:filter=<filter>. You can also enable/disable the export of certain types by setting type=true|false.

Export parameters
Name خيارات Description
fields Same as metadata field filter Default field filter to apply for all types, default is :owner.
filter Same as metadata object filter Default object filter to apply for all types, default is none.
order Same as metadata order Default order to apply to all types, default is name if available, or created if not.
translate false/true Enable translations. Be aware that this is turned off by default (in other endpoints this is on by default).
locale <locale> Change from user locale, to your own custom locale.
defaults INCLUDE/EXCLUDE Should auto-generated category object be included or not in the payload. If you are moving metadata between 2 non-synced instances, it might make sense to set this to EXCLUDE to ease the handling of these generated objects.
skipSharing false/true Enabling this will strip the sharing properties from the exported objects. This includes user, publicAccess, userGroupAccesses, userAccesses, and externalAccess.
inclusionStrategy NON_NULL, ALWAYS, NON_EMPTY NON_NULL includes properties which are not null, ALWAYS includes all properties, NON_EMPTY includes non empty properties (will not include strings of 0 length or empty collections)
download false/true Enabling this will add HTTP header Content-Disposition that specifies that the data should be handled as an attachment and will be offered by web browsers as a download.

Metadata export examples

Export all metadata. Be careful as the response might be very large depending on your metadata configuration:

/api/metadata

Export all metadata ordered by lastUpdated descending:

/api/metadata?defaultOrder=lastUpdated:desc

Export metadata only including indicators and indicator groups:

/api/metadata?indicators=true&indicatorGroups=true

Export id and displayName for all data elements, ordered by displayName:

/api/metadata?dataElements:fields=id,name&dataElements:order=displayName:desc

Export data elements and indicators where name starts with "ANC":

/api/metadata?filter=name:^like:ANC&dataElements=true&indicators=true

Metadata export with dependencies

When you want to exchange metadata for a data set, program, category combo, dashboard, option set or data element group from one DHIS2 instance to another instance there are six dedicated endpoints available:

/api/dataSets/{id}/metadata.json

/api/programs/{id}/metadata.json

/api/categoryCombos/{id}/metadata.json

/api/dashboards/{id}/metadata.json

/api/optionSets/{id}/metadata.json

/api/dataElementGroups/{id}/metadata.json

These exports can then be imported using /api/metadata.

These endpoints also support the following parameters:

Export parameters
Name خيارات Description
skipSharing false/true Enabling this will strip the sharing properties from the exported objects. This includes user, publicAccess, userGroupAccesses, userAccesses, and externalAccess.
download false/true Enabling this will add HTTP header Content-Disposition that specifies that the data should be handled as an attachment and will be offered by web browsers as a download.

Metadata import

This section explains the metadata import API. XML and JSON resource representations are supported. Metadata can be imported using a POST request.

/api/metadata

The importer allows you to import metadata payloads which may include many different entities and any number of objects per entity. The metadata export generated by the metadata export API can be imported directly.

The metadata import endpoint support a variety of parameters, which are listed below.

Import parameters
Name Options (first is default) Description
importMode COMMIT, VALIDATE Sets overall import mode, decides whether or not to only VALIDATE or also COMMIT the metadata, this has similar functionality as our old dryRun flag.
identifier UID, CODE, AUTO Sets the identifier scheme to use for reference matching. AUTO means try UID first, then CODE.
importReportMode ERRORS, FULL, DEBUG Sets the ImportReport mode, controls how much is reported back after the import is done. ERRORS only includes ObjectReports for object which has errors. FULL returns an ObjectReport for all objects imported, and DEBUG returns the same plus a name for the object (if available).
preheatMode REFERENCE, ALL, NONE Sets the preheater mode, used to signal if preheating should be done for ALL (as it was before with preheatCache=true) or do a more intelligent scan of the objects to see what to preheat (now the default), setting this to NONE is not recommended.
importStrategy CREATE_AND_UPDATE, CREATE, UPDATE, DELETE Sets import strategy, CREATE_AND_UPDATE will try and match on identifier, if it doesn't exist, it will create the object.
atomicMode ALL, NONE Sets atomic mode, in the old importer we always did a best effort import, which means that even if some references did not exist, we would still import (i.e. missing data elements on a data element group import). Default for new importer is to not allow this, and similar reject any validation errors. Setting the NONE mode emulated the old behavior.
flushMode AUTO, OBJECT Sets the flush mode, which controls when to flush the internal cache. It is strongly recommended to keep this to AUTO (which is the default). Only use OBJECT for debugging purposes, where you are seeing hibernate exceptions and want to pinpoint the exact place where the stack happens (hibernate will only throw when flushing, so it can be hard to know which object had issues).
skipSharing false, true Skip sharing properties, does not merge sharing when doing updates, and does not add user group access when creating new objects.
skipValidation false, true Skip validation for import. NOT RECOMMENDED.
async false, true Asynchronous import, returns immediately with a Location header pointing to the location of the importReport. The payload also contains a json object of the job created.
userOverrideMode NONE, CURRENT, SELECTED Allows you to override the user property of every object you are importing, the options are NONE (do nothing), CURRENT (use import user), SELECTED (select a specific user using overrideUser=X)
overrideUser User ID If userOverrideMode is SELECTED, use this parameter to select the user you want override with.

NOTE When updating objects, all property values will be overwritten even if the new values are null. Please use JSON Patch API in case you want do partial update to an object.

An example of a metadata payload to be imported looks like this. Note how each entity type have their own property with an array of objects:

{
  "dataElements": [
    {
      "name": "EPI - IPV 3 doses given",
      "shortName": "EPI - IPV 3 doses given",
      "aggregationType": "SUM",
      "domainType": "AGGREGATE",
      "valueType": "INTEGER_ZERO_OR_POSITIVE"
    },
    {
      "name": "EPI - IPV 4 doses given",
      "shortName": "EPI - IPV 4 doses given",
      "aggregationType": "SUM",
      "domainType": "AGGREGATE",
      "valueType": "INTEGER_ZERO_OR_POSITIVE"
    }
  ],
  "indicators": [
    {
      "name": "EPI - ADS stock used",
      "shortName": "ADS stock used",
      "numerator": "#{LTb8XeeqeqI}+#{Fs28ZQJET6V}-#{A3mHIZd2tPg}",
      "numeratorDescription": "ADS 0.05 ml used",
      "denominator": "1",
      "denominatorDescription": "1",
      "annualized": false,
      "indicatorType": {
        "id": "kHy61PbChXr"
      }
    }
  ]
}

When posting this payload to the metadata endpoint, the response will contain information about the parameters used during the import and a summary per entity type including how many objects were created, updated, deleted and ignored:

{
  "importParams": {
    "userOverrideMode": "NONE",
    "importMode": "COMMIT",
    "identifier": "UID",
    "preheatMode": "REFERENCE",
    "importStrategy": "CREATE_AND_UPDATE",
    "atomicMode": "ALL",
    "flushMode": "AUTO",
    "skipSharing": false,
    "skipTranslation": false,
    "skipValidation": false,
    "metadataSyncImport": false,
    "firstRowIsHeader": true,
    "username": "UNICEF_admin"
  },
  "status": "OK",
  "typeReports": [
    {
      "klass": "org.hisp.dhis.dataelement.DataElement",
      "stats": {
        "created": 2,
        "updated": 0,
        "deleted": 0,
        "ignored": 0,
        "total": 2
      }
    },
    {
      "klass": "org.hisp.dhis.indicator.Indicator",
      "stats": {
        "created": 1,
        "updated": 0,
        "deleted": 0,
        "ignored": 0,
        "total": 1
      }
    }
  ],
  "stats": {
    "created": 3,
    "updated": 0,
    "deleted": 0,
    "ignored": 0,
    "total": 3
  }
}

GeoJSON import

The GeoJSON import is used to attach geometry data to organisation units.

For a bulk import a GeoJSON file with a feature collection is expected. Each feature in the collection requires a reference to the organisation unit it should be linked to.

By default, the geometry from the file is stored as the geometry property of an organisation unit. To store additional geometries attributes of type GEOJSON can be created. When attributes are use all geometries from a file are stored for the same attribute which is provided with an additional parameter attributeId.

GeoJSON Bulk Data Import

Import Parameters
Name Type Default Description
geoJsonId boolean true When true the id property of the GeoJSON features is expected to hold the organisation unit identifier
geoJsonProperty String undefined If geoJsonId is false this parameter names the property in the GeoJSON feature's properties that holds the organisation unit identifier
orgUnitProperty enum: [id, code, name] id The property of the organisation unit that is referred to by the identifiers used in the GeoJSON file
attributeId String undefined When set the geometry is stored as value of the attribute referenced by ID
dryRun boolean false When true the import is processed without actually updating the organisation units
async boolean false When true the import is processed asnychronously

Uasge:

POST /api/organisationUnits/geometry

The post body is the GeoJSON file. Content type should be application/json or application/geo+json. The file may be .zip or .gzip compressed.

For example, a default file where id is used to refer to an organisation unit id has this structure:

{ 
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "id": "O6uvpzGd5pu",
      "geometry": { ... }
    },
    ...
  ]
}

A file where a feature property is used to refer to the organisation unit code would have this structure:

{ 
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": { "code": "OU1_CODE" },
      "geometry": { ... }
    },
    ...
  ]
}
The coordinates in a geometry may be pairs or triplets. If a third dimension is present it is stripped during the import.

A geometry may also be null to effectively clear or delete the geometry for specific organisation units. There is a special bulk deletion API that is described in the next section.

When run synchronously an import report is returned directly. The HTTP status code is always OK, the status in the message payload indicates if all rows were imported successfully. The import counts statistics contained in the report give further information:

  • imported: number of organisation units that were successfully updated with a geometry that did not have one before for the updated property
  • updated: number of organisation units that were successfully updated with a geometry that did have value for the updated property already
  • ignored: number of organisation units that failed to update
  • deleted: number of organisation units that where successfully update with a empty geometry

When the import is run asynchronous the request returns immediately with status OK and job configuration response that contains a relative reference to the task endpoint that allows to track the status of the asynchronous import. For example:

/api/system/tasks/GEOJSON_IMPORT/{job-id}

The summary that is returned directly for synchronous execution is available at

/api/system/taskSummaries/GEOJSON_IMPORT/{job-id}

once the import is finished.

GeoJSON Bulk Data Deletion

To clear or unset the geometry data for all organisation units use:

DELETE /api/organisationUnits/geometry

To clear or unset the geometry data for a specific GEOJSON attribute for all organisation units use:

DELETE /api/organisationUnits/geometry?attributeId={attr-id}

Clearing is always synchronous and returns a similar report as the bulk import. It does not support any other parameters. No dry-run can be performed. Bulk clearing requires the F_PERFORM_MAINTENANCE authority.

GeoJSON Single Data Import

The single import allows to update the geometry of a single organisation unit.

POST /api/organisationUnits/{id}/geometry

The post body only contains the GeoJSON geometry value, for example:

{
  "type": "Polygon",
  "coordinates": [...]
}
Single import only supports attributeId and dryRun parameters.

GeoJSON Single Data Deletion

To clear the geometry GeoJSON data of an individual organisation unit use:

DELETE /api/organisationUnits/{id}/geometry

Similarly to clear a GEOJSON attribute value for an individual organisation unit use:

DELETE /api/organisationUnits/{id}/geometry?attributeId={attr-id}

Clearing is always synchronous returns a similar report as single import. The dry-run parameter is supported as well. The performing user requires authority to modify the target organisation unit.

Schema

A resource which can be used to introspect all available DXF 2 objects can be found on /api/schemas. For specific resources you can have a look at /api/schemas/<type>.

To get all available schemas in XML:

GET /api/schemas.xml

To get all available schemas in JSON:

GET /api/schemas.json

To get JSON schema for a specific class:

GET /api/schemas/dataElement.json

Icons

DHIS2 includes a collection of icons that can be used to give visual context to metadata. There are two different kind of icons: - Default icons: they are pre-installed in the application and are not possible to modify nor delete. - Custom icons: can be created, updated and deleted at will.

Both of them be accessed through the icons resource.

GET /api/icons

This endpoint returns a list of information about the available default and custom icons. By default key, description, keywords and href will be included in response. But fields parameter can be used to change this behaviour.

{
  key: "mosquito_outline",
  description: "Mosquito outline",
  keywords: [
    "malaria",
    "mosquito",
    "dengue"
  ],
  "created": "2024-02-12T09:50:11.794",
  "lastUpdated": "2024-02-12T09:50:11.794",
  href: "<dhis server>/api/icons/mosquito_outline/icon.svg"
}

It's also possible to get a particular icon directly by filtering by its key, in the example below, the key is mosquito_outline.

GET /api/icons/mosquito_outline

Custom icon operations

A list of custom icons can be fetched retrieved certain request parameters

GET /api/icons?type=CUSTOM
Request parameter Type Allowed values Description
type Text DEFAULT,CUSTOM,ALL What type of icons should be retrieved. Default is ALL
keys Text List of keys custom icons should be retrieved for
keywords Text List of keywords custom icons should be retrieved for
search Text Search for a given text across icon keys and keywords, and retrieve all icons that contain this text in their key or keywords.
createdStartDate Date Starting point of created date
createdEndDate Date End point of created date
lastUpdatedStartDate Date Starting point of last updated date
lastUpdatedEndDate Date End point of last updated date

Request parameters for pagination

Request parameter Type Allowed values Description
page Integer Any positive integer Page number to return. Defaults to 1 if missing
pageSize Integer Any positive integer Page size. Defaults to 50.
paging Boolean true|false Indicates whether paging should be ignored and all rows should be returned. Defaults to true, meaning that by default all requests are paginated, unless paging=false

Request parameters for ordering

Request parameter Type Allowed values Description
order Text created:desc Comma-separated list of property name and sort direction pairs in format propName:sortDirection. By default icons will be ordered based on key:asc

Request parameter to filter responses

The endpoints accept a fields parameter which controls which fields will be returned in the JSON response. fields parameter accepts a comma separated list of field names. If nothing is specified, default fields will be used and those are

key,keywords,description,fileResourceUid,createdByUserUid,href

A custom icon resource can be downloaded by providing the icon key:

GET /api/icons/{key}/icon

Custom icons can be created, modified and deleted. To create a custom icon, use the resource below.

POST /api/icons

It expects a payload containing the icon key, description, list of keywords and the file resource uid to be linked to the data.

{
    "key": "iconKey",
    "description": "description",
    "keywords": ["keyword 1","keyword 2"],
    "fileResourceUid": "ARsqBjfB2cf"
}

Only custom icons can be updated using below resource.

PUT /api/icons

With the following payload, the icon's description and keywords would be updated.

{
    "key": "iconKey",
    "description": "new description",
    "keywords": ["new keyword 1", "new keyword 2"] 
}

Please notice that's also possible to just update one of the two. That means in case we would like to update the description while keeping the keywords, we would just need to provide the icon key and the descripton json field. Same would work the other way around, to update the keywords and leave the original description untouched.

Only custom icon can be deleted using below resource.

DELETE /api/icons/{icon_key}

Render type

Some metadata types have a property named renderType. The render type property is a map between a device and a renderingType. Applications can use this information as a hint on how the object should be rendered on a specific device. For example, a mobile device might want to render a data element differently than a desktop computer.

There is currently two different kinds of renderingTypes available:

  1. Value type rendering

  2. Program stage section rendering

There is also 2 device types available:

  1. MOBILE

  2. DESKTOP

The following table lists the metadata and rendering types available. The value type rendering has addition constraints based on the metadata configuration, which will be shown in a second table.

Metadata and RenderingType overview
Metadata type Available RenderingTypes
Program Stage Section * LISTING (default)
* SEQUENTIAL
* MATRIX
عنصر البيانات * DEFAULT
* DROPDOWN
* VERTICAL_RADIOBUTTONS
* HORIZONTAL_RADIOBUTTONS
* VERTICAL_CHECKBOXES
* HORIZONTAL_CHECKBOXES
* SHARED_HEADER_RADIOBUTTONS
* ICONS_AS_BUTTONS
* SPINNER
* ICON
* TOGGLE
* VALUE
* SLIDER
* LINEAR_SCALE
* AUTOCOMPLETE
* QR_CODE
* BAR_CODE
* GS1_DATAMATRIX

Since handling the default rendering of data elements and tracked entity attributes are depending on the value type of the object, there is also a DEFAULT type to tell the client it should be handled as normal. Program Stage Section is LISTING as default.

RenderingTypes allowed based on value types
Value type Is object an optionset? RenderingTypes allowed
TRUE_ONLY No DEFAULT, VERTICAL_RADIOBUTTONS, HORIZONTAL_RADIOBUTTONS, VERTICAL_CHECKBOXES, HORIZONTAL_CHECKBOXES, TOGGLE
BOOLEAN No
- Yes DEFAULT, DROPDOWN, VERTICAL_RADIOBUTTONS, HORIZONTAL_RADIOBUTTONS, VERTICAL_CHECKBOXES, HORIZONTAL_CHECKBOXES, SHARED_HEADER_RADIOBUTTONS, ICONS_AS_BUTTONS, SPINNER, ICON
INTEGER No DEFAULT, VALUE, SLIDER, LINEAR_SCALE, SPINNER
TEXT No DEFAULT, VALUE, AUTOCOMPLETE, QR_CODE, BAR_CODE, GS1_DATAMATRIX
INTEGER_POSITIVE No
INTEGER_NEGATIVE No
INTEGER_ZERO_OR_POSITIVE No
NUMBER No
UNIT_INTERVAL No
PERCENTAGE No

A complete reference of the previous table can also be retrieved using the following endpoint:

GET /api/staticConfiguration/renderingOptions

Value type rendering also has some additional properties that can be set, which is usually needed when rendering some of the specific types:

renderType object properties
Property Description Type
type The RenderingType of the object, as seen in the first table. This property is the same for both value type and program stage section, but is the only property available for program stage section. Enum (See list in the Metadata and Rendering Type table)
min Only for value type rendering. Represents the minimum value this field can have. Integer
max Only for value type rendering. Represents the maximum value this field can have. Integer
step Only for value type rendering. Represents the size of the steps the value should increase, for example for SLIDER og LINEAR_SCALE Integer
decimalPoints Only for value type rendering. Represents the number of decimal points the value should use. Integer

The renderingType can be set when creating or updating the metadata listed in the first table. An example payload for the rendering type for program stage section looks like this:

{
  "renderingType": {
    "type": "MATRIX"
  }
}

For data element and tracked entity attribute:

{
  "renderingType": {
    "type": "SLIDER",
    "min": 0,
    "max": 1000,
    "step": 50,
    "decimalPoints": 0
  }
}

Object Style

Most metadata have a property names "style". This property can be used by clients to represent the object in a certain way. The properties currently supported by style is as follows:

Style properties
Property Description Type
color A color, represented by a hexadecimal. String (#000000)
icon An icon, represented by a icon-name. String

Currently, there is no official list or support for icon-libraries, so this is currently up to the client to provide. The following list shows all objects that support style:

  • عنصر البيانات

  • Data element category option

  • Data set

  • Indicator

  • Option

  • Program

  • Program Indicator

  • Program Section

  • Program Stage

  • Program Stage Section

  • Relationship (Tracker)

  • Tracked Entity Attribute

  • Tracked Entity Type

When creating or updating any of these objects, you can include the following payload to change the style:

{
  "style": {
    "color": "#ffffff",
    "icon": "my-beautiful-icon"
  }
}

Category Option

Merge category options

The category option merge endpoint allows you to merge a number of category options (sources) into a target category option.

Authorisation

The main authority required to perform a category option merge is F_CATEGORY_OPTION_MERGE.
Other authorities required relate to the general sharing and access of category options, F_CATEGORY_OPTION_PUBLIC_ADD and F_CATEGORY_OPTION_DELETE.

Request

Merge category options with a POST request:

POST /api/categoryOptions/merge

The payload in JSON format looks like the following:

{
  "sources": [
    "FbLZS3ueWbQ",
    "dPSWsKeAZNw"
  ],
  "target": "rEq3Hkd3XXH",
  "deleteSources": true
}

The JSON properties are described in the following table.

Merge payload fields
Field Required Value
sources Yes Array of identifiers of the category options to merge (the source category options)
target Yes Identifier of the category option to merge the sources into (the target category option)
deleteSources No Whether to delete the source category options after the operation. Default is false.

The merge operation will merge the source category options into the target category option. One or many source category options can be specified. Only one target should be specified.

The merge operation will transfer all source category option metadata associations to the target category option. The following metadata get updated:

Metadata Property Action taken
Category categoryOptions remove sources, add target
CategoryDimension items remove sources, add target
CategoryOptionCombo categoryOptions remove sources, add target
CategoryOptionGroup members remove sources, add target
OrganisationUnit categoryOptions remove sources, add target

Validation

The following constraints and error codes apply.

Constraints and error codes
Error code Description
E1530 At least one source CategoryOption must be specified
E1531 Target CategoryOption must be specified
E1532 Target CategoryOption cannot be a source category option
E1533 Source/Target CategoryOption does not exist: {uid}

Response

Success

Sample success response looks like:

{
    "httpStatus": "OK",
    "httpStatusCode": 200,
    "status": "OK",
    "response": {
        "mergeReport": {
            "mergeErrors": [],
            "mergeType": "CategoryOption",
            "sourcesDeleted": [
                "FbLZS3ueWbQ", "dPSWsKeAZNw"
            ],
            "message": "CategoryOption merge complete"
        }
    }
}
Failure

Sample error response looks like:

{
    "httpStatus": "Conflict",
    "httpStatusCode": 409,
    "status": "WARNING",
    "message": "One or more errors occurred, please see full details in merge report.",
    "response": {
        "mergeReport": {
            "mergeErrors": [
                {
                    "message": "At least one source CategoryOption must be specified",
                    "errorCode": "E1530",
                    "args": []
                },
                {
                    "message": "Target CategoryOption does not exist: `abcdefg1221`",
                    "errorCode": "E1533",
                    "args": [
                        "Target",
                        "abcdefg1221"
                    ]
                }
            ],
            "mergeType": "CategoryOption",
            "sourcesDeleted": [],
            "message": "CategoryOption merge has errors"
        }
    }
}

Category Option Combo

Merge category option combos

The category option combo merge endpoint allows you to merge a number of category options (sources) into a target category option. This can be used to clean up the system, removing duplicates for instance.

Note

Only duplicate category option combos can be merged. There's more info about this in the validation section below.

Authorisation

The main authority required to perform a category option combo merge is F_CATEGORY_OPTION_COMBO_MERGE.

Request

Merge category option combos with a POST request:

POST /api/categoryOptionCombos/merge

The payload in JSON format looks like the following:

{
  "sources": [
    "FbLZS3ueWbQ",
    "dPSWsKeAZNw"
  ],
  "target": "rEq3Hkd3XXH",
  "dataMergeStrategy": "DISCARD"
}

The JSON properties are described in the following table.

Merge payload fields
Field Required Value
sources Yes Array of identifiers of the category option combos to merge (the source category option combos)
target Yes Identifier of the category option combo to merge the sources into (the target category option combo)
dataMergeStrategy Yes How to handle merging of data values. Options are 'DISCARD' or 'LAST_UPDATED'. DISCARD will delete all source data values. LAST_UPDATED will merge all data values and use the last updated value where duplicates are met.

The merge operation will merge the source category option combos into the target category option combo. One or many source category option combos can be specified. Only one target should be specified.

The merge operation will transfer all source category option combo metadata associations to the target category option combo.

Note

All source category option combos will always be deleted during a merge. The is because after all source references have been handled, empty category option combos are left. These are not seen as valid by the system.

The following metadata get updated:

Metadata Property Action taken
CategoryOption categoryOptionCombos remove sources
CategoryCombo optionCombos remove sources
DataElementOperand categoryOptionCombo set as target
DataDimensionItem dataelementoperand_categoryoptioncomboid set as target
التعبير expression replace source with target
Indicator numerator replace source with target
Indicator denominator replace source with target
MinMaxDataElement optionCombo set as target
Predictor outputCombo set as target
SMSCode optionId set as target
Data Property Action taken
DataValue categoryOptionCombo merge strategy (DISCARD or LAST_UPDATED)
DataValue attributeOptionCombo merge strategy (DISCARD or LAST_UPDATED)
DataApproval attributeOptionCombo merge strategy (DISCARD or LAST_UPDATED)
DataApprovalAudit attributeOptionCombo DISCARD or leave depending if sources are deleted or not
Event attributeOptionCombo merge strategy (DISCARD or LAST_UPDATED)
DataValueAudit categoryOptionCombo DISCARD or leave depending if sources are deleted or not
DataValueAudit attributeOptionCombo DISCARD or leave depending if sources are deleted or not
CompleteDataSetRegistration attributeOptionCombo merge strategy (DISCARD or LAST_UPDATED)

Note

The following properties haven been purposely excluded from the merge as these may use references for external systems. If you encounter issues with these fields, they may need to be updated.

Indicator: aggregateExportCategoryOptionCombo & aggregateExportAttributeOptionCombo

ProgramIndicator: aggregateExportCategoryOptionCombo & aggregateExportAttributeOptionCombo

Validation

The following constraints and error codes apply. One of the main validation points is regarding duplicate CategoryOptionCombos. A duplicate CategoryOptionCombo is one which satisfies the criteria: - has the same CategoryCombo - has the same CategoryOptions - has a different UID

Constraints and error codes
Error code Description
E1530 At least one source CategoryOptionCombo must be specified
E1531 Target CategoryOptionCombo must be specified
E1532 Target CategoryOptionCombo cannot be a source CategoryOptionCombo
E1533 Source/Target CategoryOptionCombo does not exist: {uid}
E1534 dataMergeStrategy field must be specified. With value DISCARD or LAST_UPDATED
E1540 CategoryOptionCombos must be duplicates (same cat combo, same cat options, different UID) in order to merge

Database constraints

There are unique constraints in place that can prevent a successful merge. These constraints are set by DHIS2 in order to maintain a logical domain model.
Below are a list of the known database unique key constraints at the time of writing. For example, you can only have 1 min max data element with the same org unit, data element and category option combo.

Database table unique key constraints
Table Unique key constraint
minmaxdataelement orgunit, dataelement, categoryoptioncombo

Response

Success

Sample success response looks like:

{
    "httpStatus": "OK",
    "httpStatusCode": 200,
    "status": "OK",
    "response": {
        "mergeReport": {
            "mergeErrors": [],
            "mergeType": "CategoryOptionCombo",
            "sourcesDeleted": [
                "FbLZS3ueWbQ", "dPSWsKeAZNw"
            ],
            "message": "CategoryOptionCombo merge complete"
        }
    }
}
Failure

Sample error response looks like:

{
    "httpStatus": "Conflict",
    "httpStatusCode": 409,
    "status": "WARNING",
    "message": "One or more errors occurred, please see full details in merge report.",
    "response": {
        "mergeReport": {
            "mergeErrors": [
                {
                    "message": "At least one source CategoryOptionCombo must be specified",
                    "errorCode": "E1530",
                    "args": []
                },
                {
                    "message": "Target CategoryOptionCombo does not exist: `abcdefg1221`",
                    "errorCode": "E1533",
                    "args": [
                        "Target",
                        "abcdefg1221"
                    ]
                }
            ],
            "mergeType": "CategoryOptionCombo",
            "sourcesDeleted": [],
            "message": "CategoryOptionCombo merge has errors"
        }
    }
}

A database constraint sample error response:

{
  "httpStatus": "Conflict",
  "httpStatusCode": 409,
  "status": "ERROR",
  "message": "ERROR: duplicate key value violates unique constraint \"minmaxdataelement_unique_key\"\n  Detail: Key (sourceid, dataelementid, categoryoptioncomboid)=(193236, 1148617, 167661) already exists."
}

Data Elements

Merge data elements

Caution

Merging DataElements should be carried out with the utmost care. Particular attention should be given to the merging of data values that have data element references involved in the merge. Knowing the potential side effects of a merge should be fully understood before performing the merge. The merging of DataElements has far-reaching effects. The information below will try to help show what's involved in a DataElement merge. A DataElement merge touches all the major parts of the system (metadata, data, tracker, analytics and audit).

System performance may be impacted if the source DataElements are linked to large amounts of Data/Audit records particularly.

The data element merge endpoint allows you to merge a number of data elements (sources) into a target data element.

Authorisation

The main authority required to perform a data element merge is F_DATA_ELEMENT_MERGE.
Other authorities required relate to the general sharing and access of data elements, F_DATAELEMENT_PUBLIC_ADD and F_DATAELEMENT_DELETE.

Request

Merge data elements with a POST request:

POST /api/dataElements/merge

The payload in JSON format looks like the following:

{
  "sources": [
    "jNb63DIHuwU",
    "WAjjFMDJKcx"
  ],
  "target": "V9rfpjwHbYg",
  "deleteSources": true,
  "dataMergeStrategy": "DISCARD"
}

The JSON properties are described in the following table.

Merge payload fields
Field Required Value
sources Yes Array of identifiers of the data elements to merge (the source data elements)
target Yes Identifier of the data element to merge the sources into (the target data element)
deleteSources No Whether to delete the source data elements after the operation. Default is false. If true is chosen, then all source audit records will also be deleted.
dataMergeStrategy Yes How to handle merging of data values. Options are 'DISCARD' or 'LAST_UPDATED'. DISCARD will delete all source data values. LAST_UPDATED will merge all data values and use the last updated value where duplicates are met.

The merge operation will merge the source data elements into the target data element. One or many source data elements can be specified. Only one target should be specified.

The merge operation will transfer all source data element metadata associations to the target data element. The following metadata get updated:

Metadata Property Action taken
DataDimensionItem dataElement set to target
EventVisualization dataElementValueDimension set to target
ProgramStageDataElement dataElement set to target
ProgramNotificationTemplate recipientDataElement set to target
ProgramRuleVariable dataElement set to target
ProgramRuleAction dataElement set to target
TrackedEntityDataElementDimension dataElement set to target
MinMaxDataElement dataElement set to target
SMSCode dataElement set to target
SMSCode dataElement set to target
Predictor output set to target
DataSetElement dataElement set to target
DataElementOperand dataElement set to target
ProgramStageDataElement dataElements remove sources, add target
القسم dataElements remove sources, add target
DataElementGroup members remove sources, add target
Event eventDataValues remove sources, add target
Indicator numerator replace source with target
Indicator denominator replace source with target
Predictor generator replace source with target
Predictor sampleSkipTest replace source with target
DataEntryForm htmlCode replace source with target
ProgramIndicator expression replace source with target
ProgramIndicator filter replace source with target
DataValue dataElement
Data Property Action taken
Event eventDataValues action based on merge strategy (DISCARD / LAST_UPDATED). DISCARD will delete all source event data values. LAST_UPDATED will use the event data value which was last updated, when more than one exists.
DataValue dataElement action based on merge strategy (DISCARD / LAST_UPDATED). DISCARD will delete all source data values. LAST_UPDATED will use the data value which was last updated, when more than one exists.
TrackedEntityDataValueChangeLog deleted if sources are being deleted, otherwise no action.
DataValueAudit deleted if sources are being deleted, otherwise no action.

Validation

The following constraints and error codes apply.

Constraints and error codes
Error code Description
E1530 At least one source DataElement must be specified
E1531 Target DataElement must be specified
E1532 Target DataElement cannot be a source indicator
E1533 Source/Target DataElement does not exist: {uid}
E1550 All source ValueTypes must match target ValueType: ValueType. Other ValueTypes found: ValueType
E1551 All source DataElementDomains must match target DataElementDomain: DataElementDomain. Other DataElementDomains found: DataElementDomain
E1534 dataMergeStrategy field must be specified. With value DISCARD or LAST_UPDATED

Database constraints

There are unique constraints in place that can prevent a successful merge. These constraints are set by DHIS2 in order to maintain a logical domain model.
Below are a list of the known database unique key constraints at the time of writing. For example, you can only have 1 data set element with the same dataset and data element.

Database table unique key constraints
Table Unique key constraint
minmaxdataelement orgunit, dataelement, categoryoptioncombo
programstagedataelement programstage, dataelement
datasetelement dataset, dataelement

Response

Success

Sample success response looks like:

{
    "httpStatus": "OK",
    "httpStatusCode": 200,
    "status": "OK",
    "response": {
        "mergeReport": {
            "mergeErrors": [],
            "mergeType": "DataElement",
            "sourcesDeleted": [
                "vQ0dGV9EDrw"
            ],
            "message": "DataElement merge complete"
        }
    }
}
Failure

Sample error response looks like:

{
    "httpStatus": "Conflict",
    "httpStatusCode": 409,
    "status": "WARNING",
    "message": "One or more errors occurred, please see full details in merge report.",
    "response": {
        "mergeReport": {
            "mergeErrors": [
                {
                    "message": "At least one source DataElement must be specified",
                    "errorCode": "E1530",
                    "args": []
                },
                {
                    "message": "Target DataElement does not exist: `abcdefg1221`",
                    "errorCode": "E1533",
                    "args": [
                        "Target",
                        "abcdefg1221"
                    ]
                }
            ],
            "mergeType": "DataElement",
            "sourcesDeleted": [],
            "message": "DataElement merge has errors"
        }
    }
}

Another sample validation error response:

{
    "httpStatus": "Conflict",
    "httpStatusCode": 409,
    "status": "WARNING",
    "message": "One or more errors occurred, please see full details in merge report.",
    "response": {
        "mergeReport": {
            "mergeErrors": [
                {
                    "message": "All source ValueTypes must match target ValueType: `TEXT`. Other ValueTypes found: `NUMBER`",
                    "errorCode": "E1550",
                    "args": []
                }
            ],
            "mergeType": "DataElement",
            "sourcesDeleted": [],
            "message": "DataElement merge has errors"
        }
    }
}

A database constraint sample error response:

{
  "httpStatus": "Conflict",
  "httpStatusCode": 409,
  "status": "ERROR",
  "message": "ERROR: duplicate key value violates unique constraint \"minmaxdataelement_unique_key\"\n  Detail: Key (sourceid, dataelementid, categoryoptioncomboid)=(193236, 1148617, 167661) already exists."
}

Indicators

This section describes indicators and indicator expressions.

Aggregate indicators

To retrieve indicators you can make a GET request to the indicators resource like this:

/api/indicators

Indicators represent expressions which can be calculated and presented as a result. The indicator expressions are split into a numerator and denominator. The numerators and denominators are mathematical expressions which can contain references to data elements, other indicators, constants and organisation unit groups. The variables will be substituted with data values when used e.g. in reports. Variables which are allowed in expressions are described in the following table.

Indicator variables
Variable Object Description
#{<data-element-id>.<category-option-combo-id>.<attribute-option-combo-id>} Data element operand Refers to a combination of an aggregate data element and a category option combination. Both category and attribute option combo ids are optional, and a wildcard "*" symbol can be used to indicate any value.
#{<dataelement-id>.<category-option-group-id>.<attribute-option-combo-id>} Category Option Group Refers to an aggregate data element and a category option group, containing multiple category option combinations.
#{<data-element-id>} Aggregate data element Refers to the total value of an aggregate data element across all category option combinations.
D{<program-id>.<data-element-id>} Program data element Refers to the value of a tracker data element within a program.
A{<program-id>.<attribute-id>} Program tracked entity attribute Refers to the value of a tracked entity attribute within a program.
I{<program-indicator-id>} Program indicator Refers to the value of a program indicator.
R{<dataset-id>.<metric>} Reporting rate Refers to a reporting rate metric. The metric can be REPORTING_RATE, REPORTING_RATE_ON_TIME, ACTUAL_REPORTS, ACTUAL_REPORTS_ON_TIME, EXPECTED_REPORTS.
C{<constant-id>} Constant Refers to a constant value.
N{<indicator-id>} Indicator Refers to an existing Indicator.
OUG{<orgunitgroup-id>} Organisation unit group Refers to the count of organisation units within an organisation unit group.

Within a Data element operand or an Aggregate data element, the following substitutions may be made:

Item Value Description
data-element-id data-element-id An aggregate data element
data-element-id deGroup:data-element-group-id All the aggregate data elements in a data element group
category-option-combo-id category-option-combo-id A category option combination
category-option-combo-id co:category-option-id All the category option combinations in a category option
category-option-combo-id coGroup:category-option-group-id All the category option combinations in a category option group
category-option-combo-id coGroup:co-group-id1&co-group-id2... All the category option combinations that are members of multiple category option groups

The syntax looks like this:

#{<dataelement-id>.<catoptcombo-id>} + C{<constant-id>} + OUG{<orgunitgroup-id>}

A corresponding example looks like this:

#{P3jJH5Tu5VC.S34ULMcHMca} + C{Gfd3ppDfq8E} + OUG{CXw2yu5fodb}

Note that for data element variables the category option combo identifier can be omitted. The variable will then represent the total for the data element, e.g. across all category option combos. Example:

#{P3jJH5Tu5VC} + 2

Data element operands can include any of category option combination and attribute option combination, and use wildcards to indicate any value:

#{P3jJH5Tu5VC.S34ULMcHMca} + #{P3jJH5Tu5VC.*.j8vBiBqGf6O} + #{P3jJH5Tu5VC.S34ULMcHMca.*}

An example using a data element group:

#{deGroup:oDkJh5Ddh7d} + #{deGroup:GBHN1a1Jddh.j8vBiBqGf6O}

An example using a category option, data element group, and a category option group:

#{P3jJH5Tu5VC.co:FbLZS3ueWbQ} + #{deGroup:GBHN1a1Jddh.coGroup:OK2Nr4wdfrZ.j8vBiBqGf6O}

An example using multiple category option groups:

#{P3jJH5Tu5VC.coGroup:OK2Nr4wdfrZ&j3C417uW6J7&ddAo6zmIHOk}

An example using a program data element and a program attribute:

( D{eBAyeGv0exc.vV9UWAZohSf} * A{IpHINAT79UW.cejWyOfXge6} ) / D{eBAyeGv0exc.GieVkTxp4HH}

An example combining program indicators and aggregate indicators:

I{EMOt6Fwhs1n} * 1000 / #{WUg3MYWQ7pt}

An example using a reporting rate:

R{BfMAe6Itzgt.REPORTING_RATE} * #{P3jJH5Tu5VC.S34ULMcHMca}

Another reporting rate example using actual data set reports and expected reports:

R{BfMAe6Itzgt.ACTUAL_REPORTS} / R{BfMAe6Itzgt.EXPECTED_REPORTS}

An example using an existing indicator:

N{Rigf2d2Zbjp} * #{P3jJH5Tu5VC.S34ULMcHMca}

Expressions can be any kind of valid mathematical expression, as an example:

( 2 * #{P3jJH5Tu5VC.S34ULMcHMca} ) / ( #{FQ2o8UBlcrS.S34ULMcHMca} - 200 ) * 25

Program indicators

To retrieve program indicators you can make a GET request to the program indicators resource like this:

/api/programIndicators

Program indicators can contain information collected in a program. Indicators have an expression which can contain references to data elements, attributes, constants and program variables. Variables which are allowed in expressions are described in the following table.

Program indicator variables
Variable Description
#{<programstage-id>.<dataelement-id>} Refers to a combination of program stage and data element id.
A{<attribute-id>} Refers to a tracked entity attribute.
V{<variable-id>} Refers to a program variable.
C{<constant-id>} Refers to a constant.

The syntax looks like this:

#{<programstage-id>.<dataelement-id>} + #{<attribute-id>} + V{<varible-id>} + C{<constant-id>}

A corresponding example looks like this:

#{A03MvHHogjR.a3kGcGDCuk6} + A{OvY4VVhSDeJ} + V{incident_date} + C{bCqvfPR02Im}

Expressions

Expressions are mathematical formulas which can contain references to data elements, constants and organisation unit groups. To validate and get the textual description of an expression, you can make a GET request to the expressions resource:

/api/expressions/description?expression=<expression-string>

The response follows the standard JSON web message format. The status property indicates the outcome of the validation and will be "OK" if successful and "ERROR" if failed. The message property will be "Valid" if successful and provide a textual description of the reason why the validation failed if not. The description provides a textual description of the expression.

{
  "httpStatus": "OK",
  "httpStatusCode": 200,
  "status": "OK",
  "message": "Valid",
  "description": "Acute Flaccid Paralysis"
}

Merge indicators

The indicator merge endpoint allows you to merge a number of indicators (sources) into a target indicator.

Authorisation

The authority F_INDICATOR_MERGE is required to perform indicator merges.

Request

Merge indicators with a POST request:

POST /api/indicators/merge

The payload in JSON format looks like the following:

{
  "sources": [
    "jNb63DIHuwU",
    "WAjjFMDJKcx"
  ],
  "target": "V9rfpjwHbYg",
  "deleteSources": true
}

The JSON properties are described in the following table.

Merge payload fields
Field Required Value
sources Yes Array of identifiers of the indicators to merge (the source indicators)
target Yes Identifier of the indicator to merge the sources into (the target indicator)
deleteSources No Whether to delete the source indicators after the operation. Default is false

The merge operation will merge the source indicators into the target indicator. One or many source indicators can be specified. Only one target should be specified.

The merge operation will transfer all source indicator metadata associations to the target indicator. The following metadata get updated:

Metadata Property Action taken
IndicatorGroup members Source indicator removed, target indicator added
DataSet indicators Source indicator removed, target indicator added
DataDimensionalItem n/a Any linked data items with sources will be linked with the target
القسم indicators Source indicator removed, target indicator added
Configuration infrastructuralIndicators (IndicatorGroup) Source indicator removed, target indicator added
Indicator numerator / denominator Replace any source reference with the target reference
DataEntryForm htmlCode Replace any source reference with the target reference
Visualization sorting Replace any source reference with the target reference as Sorting dimension

Validation

The following constraints and error codes apply.

Constraints and error codes
Error code Description
E1530 At least one source indicator must be specified
E1531 Target indicator must be specified
E1532 Target indicator cannot be a source indicator
E1533 Source/Target indicator does not exist: {uid}

Response

Success

Sample success response looks like:

{
    "httpStatus": "OK",
    "httpStatusCode": 200,
    "status": "OK",
    "response": {
        "mergeReport": {
            "mergeErrors": [],
            "mergeType": "Indicator",
            "sourcesDeleted": [
                "vQ0dGV9EDrw"
            ],
            "message": "Indicator merge complete"
        }
    }
}

Sample error response looks like:

{
    "httpStatus": "Conflict",
    "httpStatusCode": 409,
    "status": "WARNING",
    "message": "One or more errors occurred, please see full details in merge report.",
    "response": {
        "mergeReport": {
            "mergeErrors": [
                {
                    "message": "At least one source Indicator must be specified",
                    "errorCode": "E1530",
                    "args": []
                },
                {
                    "message": "Target Indicator does not exist: `abcdefg1221`",
                    "errorCode": "E1533",
                    "args": [
                        "Target",
                        "abcdefg1221"
                    ]
                }
            ],
            "mergeType": "Indicator",
            "sourcesDeleted": [],
            "message": "Indicator merge has errors"
        }
    }
}

Indicator Types

Merge indicator types

The indicator type merge endpoint allows you to merge a number of indicator types into a target indicator type.

Authorisation

The authority F_INDICATOR_TYPE_MERGE is required to perform indicator type merges.

Request

Merge indicator types with a POST request:

POST /api/indicatorTypes/merge

The payload in JSON format looks like the following:

{
  "sources": [
    "jNb63DIHuwU",
    "WAjjFMDJKcx"
  ],
  "target": "V9rfpjwHbYg",
  "deleteSources": true
}

The JSON properties are described in the following table.

Merge payload fields
Field Required Value
sources Yes Array of identifiers of the indicator types to merge (the source indicator types).
target Yes Identifier of the indicator type to merge the sources into (the target indicator type).
deleteSources No Whether to delete the source indicator types after the operation. Default is false.

The merge operation will merge the source indicator types into the target indicator type. One or many source indicator types can be specified. Only one target should be specified.

The merge operation will transfer all of the indicator metadata associations to the source indicator types over to the target indicator type.

Validation

The following constraints and error codes apply.

Constraints and error codes
Error code Description
E1530 At least one source IndicatorType must be specified
E1531 Target IndicatorType must be specified
E1532 Target IndicatorType cannot be a source indicator type
E1533 Source/Target IndicatorType does not exist: {uid}

Response

Success

Sample success response looks like:

{
    "httpStatus": "OK",
    "httpStatusCode": 200,
    "status": "OK",
    "response": {
        "mergeReport": {
            "mergeErrors": [],
            "mergeType": "IndicatorType",
            "sourcesDeleted": [
                "vQ0dGV9EDrw"
            ],
            "message": "IndicatorType merge complete"
        }
    }
}

Sample error response looks like:

{
    "httpStatus": "Conflict",
    "httpStatusCode": 409,
    "status": "WARNING",
    "message": "One or more errors occurred, please see full details in merge report.",
    "response": {
        "mergeReport": {
            "mergeErrors": [
                {
                    "message": "At least one source IndicatorType must be specified",
                    "errorCode": "E1530",
                    "args": []
                },
                {
                    "message": "Target IndicatorType does not exist: `abcdefg1221`",
                    "errorCode": "E1533",
                    "args": [
                        "Target",
                        "abcdefg1221"
                    ]
                }
            ],
            "mergeType": "IndicatorType",
            "sourcesDeleted": [],
            "message": "IndicatorType merge has errors"
        }
    }
}

Organisation units

The organisationUnits resource follows the standard conventions as other metadata resources in DHIS2. This resource supports some additional query parameters.

Get list of organisation units

To get a list of organisation units you can use the following resource.

/api/33/organisationUnits
Organisation units query parameters
Query parameter خيارات Description
userOnly false | true Data capture organisation units associated with current user only.
userDataViewOnly false | true Data view organisation units associated with current user only.
userDataViewFallback false | true Data view organisation units associated with current user only with fallback to data capture organisation units.
query string Query against the name, code and ID properties.
level integer Organisation units at the given level in the hierarchy.
maxLevel integer Organisation units at the given max level or levels higher up in the hierarchy.
withinUserHierarchy false | true Limits search and retrieval to organisation units that are within the users data capture scope.
withinUserSearchHierarchy false | true Limits search and retrieval to organisation units that are within the current users search scope. Note: "withinUserHierarchy", if true, takes higher precedence.
memberCollection string For displaying count of members within a collection, refers to the name of the collection associated with organisation units.
memberObject UID For displaying count of members within a collection, refers to the identifier of the object member of the collection.

Get organisation unit with sub-hierarchy

To get an organisation unit including organisation units in its sub-hierarchy you can use the following resource.

/api/33/organisationUnits/{id}
Organisation unit parameters
Query parameter خيارات Description
includeChildren false | true Include immediate children of the specified organisation unit, i.e. the units at the immediate level below in the subhierarchy.
includeDescendants false | true Include all children of the specified organisation unit, i.e. all units in the sub-hierarchy.
includeAncestors false | true Include all parents of the specified organisation unit.
level integer Include children of the specified organisation unit at the given level of the sub-hierarchy. This is relative to the organisation unit, starting on 1 for the level immediately below the org unit.

Get organisation units by category option

Purpose-built endpoint to retrieve associations between category options and organisation units. This endpoint is the preferred way to retrieve program organisation unit associations.

/api/33/categoryOptions/orgUnits?categoryOptions={categoryOptionIdA},{categoryOptionIdB}

responses will have the following format:

{
  "<categoryOptionIdA>": [
    "<orgUnitUid>",
    "<orgUnitUid>"
  ],
  "<categoryOptionIdB>": [
    "<orgUnitUid>",
    "<orgUnitUid>"
  ],
  "<categoryOptionIdC>": []
}

Category options that are accessible by all organisation units are returned with an empty array ([]) of organisation units.

Get organisation units by programs

Purpose-built endpoint to retrieve associations between programs and organisation units. This endpoint is the preferred way to retrieve program organisation unit associations.

/api/33/programs/orgUnits?programs={programIdA},{programIdB}

responses will have the following format:

{
  "<programIdA>": [
    "<orgUnitUid>",
    "<orgUnitUid>"
  ],
  "<programIdB>": [
    "<orgUnitUid>",
    "<orgUnitUid>"
  ],
  "<programIdC>": []
}

Programs which are accessible by all organisation units are returned with an empty array ([]) of organisation units.

Split organisation unit

The organisation unit split endpoint allows you to split organisation units into a number of target organisation units.

Request

Split organisation units with a POST request:

POST /api/organisationUnits/split

The payload in JSON format looks like the following:

{
  "source": "rspjJHg4WY1",
  "targets": [
    "HT0w9YLMLyn",
    "rEpnzuNpRKM"
  ],
  "primaryTarget": "HT0w9YLMLyn",
  "deleteSource": true
}

The JSON properties are described in the following table.

Split payload fields
Field Required Value
source Yes Identifier of the organisation unit to split (the source organisation unit).
targets Yes Array of identifiers of the organisation units to split the source into (the target organisation units).
primaryTarget No Identifier of the organisation unit to transfer the aggregate data, events and tracked entities associated with the source over to. If not specified, the first target will be used.
deleteSource No Whether to delete the source organisation unit after the operation. Default is true.

The split operation will split the source org unit into the target org units. It is recommended to first create new target org units before performing the split, and at a minimum ensure that no aggregate data exists for the target org units. Any number of target org units can be specified.

The split operation will transfer all of the metadata associations of the source org unit over to the target org units. This includes data sets, programs, org unit groups, category options, users, visualizations, maps and event reports.

The operation will transfer all data records of the source org unit over to the org unit specified as the primary target, or if not specified, the first specified target org unit. This includes aggregate data values, data approval records, events, tracked entities and more.

Validation

The following constraints and error codes apply.

Constraints and error codes
Error code Description
E1510 Source org unit must be specified
E1511 At least two target org units must be specified
E1512 Source org unit cannot be a target org unit
E1513 Primary target must be specified
E1514 Primary target must be a target org unit
E1515 Target org unit does not exist

Merge organisation units

The organisation unit merge endpoint allows you to merge a number of organisation units into a target organisation unit.

Authorisation

The main authority required to perform an organisation unit merge is F_ORGANISATION_UNIT_MERGE.

Request

Merge organisation units with a POST request:

POST /api/organisationUnits/merge

The payload in JSON format looks like the following:

{
  "sources": [
    "jNb63DIHuwU",
    "WAjjFMDJKcx"
  ],
  "target": "V9rfpjwHbYg",
  "dataValueMergeStrategy": "LAST_UPDATED",
  "dataApprovalMergeStrategy": "LAST_UPDATED",
  "deleteSources": true
}

The JSON properties are described in the following table.

Merge payload fields
Field Required Value
sources Yes Array of identifiers of the organisation units to merge (the source organisation units).
target Yes Identifier of the organisation unit to merge the sources into (the target organisation unit).
dataValueMergeStrategy No Strategy for merging data values. Options: LAST_UPDATED (default), DISCARD.
dataApprovalMergeStrategy No Strategy for merging data approval records. Options: LAST_UPDATED (default), DISCARD.
deleteSources No Whether to delete the source organisation units after the operation. Default is true.

The merge operation will merge the source org units into the target org unit. It is recommended to first create a new target org unit before performing the merge, and at a minimum ensure that no aggregate data exists for the target org unit. Any number of source org units can be specified.

The merge operation will transfer all of the metadata associations of the source org units over to the target org unit. This includes data sets, programs, org unit groups, category options, users, visualizations, maps and event reports. The operation will also transfer all event and tracker data, such as events, enrollments, ownership history, program ownership and tracked entities, over to the target org unit.

The specified data value merge strategy defines how data values are handled. For strategy LAST_UPDATED, data values for all source org units are transferred over to the target org unit, and in situation where data values exist for the same parameters, the last updated or created data value will be used. This is done to avoid duplication of data. For strategy DISCARD, data values are not transferred over to the target org unit, and simply deleted. The specified data approval merge strategy defines how data approval records are handled, and follows the same logic as data values.

Validation

The following constraints and error codes apply.

Constraints and error codes
Error code Description
E1500 At least two source orgs unit must be specified
E1501 Target org unit must be specified
E1502 Target org unit cannot be a source org unit
E1503 Source org unit does not exist

Data sets

The dataSets resource follows the standard conventions as other metadata resources in DHIS2. This resource supports some additional query parameters.

/api/33/dataSets

To retrieve the version of a data set you can issue a GET request:

GET /api/33/dataSets/<uid>/version

To bump (increase by one) the version of a data set you can issue a POST request:

POST /api/33/dataSets/<uid>/version

Data set notification template

The dataset notification templates resource follows the standard conventions as other metadata resources in DHIS2.

GET /api/33/dataSetNotficationTemplates

To retrieve data set notification template you can issue a GET request:

GET /api/33/dataSetNotficationTemplates/<uid>

To add data set notification template you can issue a POST request:

POST /api/33/dataSetNotficationTemplates

To delete data set notification template you can issue a DELETE request:

DELETE /api/33/dataSetNotficationTemplates/<uid>

JSON payload sample is given below:

{
  "name": "dataSetNotificationTemplate1",
  "dataSetNotificationTrigger": "DATA_SET_COMPLETION",
  "relativeScheduledDays": 0,
  "notificationRecipient": "ORGANISATION_UNIT_CONTACT",
  "dataSets": [{
    "id": "eZDhcZi6FLP"
  }],
  "deliveryChannels": ["SMS","EMAIL"],
  "subjectTemplate": "V{data_set_name}",
  "messageTemplate": "V{data_set_name}V{registration_period}",
  "sendStrategy": "SINGLE_NOTIFICATION"
}

notificationRecipient can be one of: - USER_GROUP for internal messages - ORGANISATION_UNIT_CONTACT for external messages

Filled organisation unit levels

The filledOrganisationUnitLevels resource provides an ordered list of organisation unit levels, where generated levels are injected into the list to fill positions for which it does not exist a persisted level.

GET /api/33/filledOrganisationUnitLevels

To set the organisation unit levels you can issue a POST request with a JSON payload and content type application/json looking like this:

{
  "organisationUnitLevels": [{
    "name": "National",
    "level": 1,
    "offlineLevels": 3
  }, {
    "name": "District",
    "level": 2
  }, {
    "name": "Chiefdom",
    "level": 3
  }, {
    "name": "Facility",
    "level": 4
  }]
}

Predictors

A predictor allows you to generate data values based on an expression. This can be used for example to generate targets, thresholds, or estimated values.

To retrieve predictors you can make a GET request to the predictors resource like this:

/api/predictors

Creating a predictor

You can create a predictor with a POST request to the predictors resource:

POST /api/predictors

A sample payload looks like this:

{
  "id": "AG10KUJCrRk",
  "name": "Malaria Outbreak Threshold Predictor",
  "shortName": "Malaria Outbreak Predictor",
  "description": "Computes the threshold for potential malaria outbreaks based on the mean plus 1.5x the std dev",
  "output": {
    "id": "nXJJZNVAy0Y"
  },
  "generator": {
    "expression": "AVG(#{r6nrJANOqMw})+1.5*STDDEV(#{r6nrJANOqMw})",
    "description": "Maximum normal malaria case count",
    "missingValueStrategy": "NEVER_SKIP",
    "slidingWindow": false
  },
  "periodType": "Monthly",
  "sequentialSampleCount": 4,
  "sequentialSkipCount": 1,
  "annualSampleCount": 3,
  "organisationUnitLevels": [4]
}

The output element refers to the identifier of the data element for which to saved predicted data values. The generator element refers to the expression to use when calculating the predicted values.

Predictor expressions

A predictor always has a generator expression that describes how the predicted value is calculated. A predictor may also have a skip test expression returning a boolean value. When the skip test expression is present, it is evaluated in each of the sampled periods to tell whether values from that period should be skipped.

The following variables may be used in either a generator expression or a skip test expression:

Variable Object Description
#{} Aggregate data element Refers to the total value of an aggregate data element across all category option combinations.
#{. Data element operand Refers to a combination of an aggregate data element and a category option combination.
D{.} Program data element Refers to the value of a tracker data element within a program.
A{.} Program tracked entity attribute Refers to the value of a tracked entity attribute within a program.
I{} Program indicator Refers to the value of a program indicator.
R{.} Reporting rate Refers to a reporting rate metric. The metric can be REPORTING_RATE, REPORTING_RATE_ON_TIME, ACTUAL_REPORTS, ACTUAL_REPORTS_ON_TIME, EXPECTED_REPORTS.
C{} Constant Refers to a constant value.
OUG{} Organisation unit group Refers to the count of organisation units within an organisation unit group.
[days] Number of days The number of days in the current period.

Generating predicted values

To run all predictors (generating predicted values) you can make a POST request to the run resource:

POST /api/predictors/run

To run a single predictor you can make a POST request to the run resource for a predictor:

POST /api/predictors/AG10KUJCrRk/run

Program rules

This section is about sending and reading program rules, and explains the program rules data model. The program rules give functionality to configure dynamic behaviour in the programs in DHIS2.

Program rule model

The program rules data model consists of programRuleVariables, programRules and programRuleActions. The programRule contains an expression - when this expression is true, the child programRuleActions is triggered. The programRuleVariables is used to address data elements, tracked entity data values and other data values needed to run the expressions. All programRules in a program share the same library of programRuleVariables, and one programRuleVariable can be used in several programRules' expressions.

Program rule model details

The following table gives a detailed overview over the programRule model.

programRule
name description Compulsory
program The program of which the programRule is executed in. Compulsory
name The name with which the program rule will be displayed to dhis2 configurators. Not visible to the end user of the program. Compulsory
description The description of the program rule, can be used by configurators to describe the rule. Not visible to the end user of the program. Compulsory
programStage If a programStage is set for a program rule, the rule will only be evaluated inside the specified program stage. optional
condition The expression that needs to be evaluated to true in order for the program rule to trigger its child actions. The expression is written using operators, function calls, hard coded values, constants and program rule variables. d2:hasValue('hemoglobin') && #{hemoglobin} <= 7 Compulsory
priority The priority to run the rule in cases where the order of the rules matters. In most cases the rules does not depend on being run before or after other rules, and in these cases the priority can be omitted. If no priority is set, the rule will be run after any rules that has a priority defined. If a priority(integer) is set, the rule with the lowest priority will be run before rules with higher priority. optional

Program rule action model details

The following table gives a detailed overview over the programRuleAction model.

programRuleAction
name description Compulsory
programRule The programRule that is the parent of this action. Compulsory
programRule- ActionType The type of action that is to be performed.
* DISPLAYTEXT - Displays a text in a given widget.
* DISPLAYKEYVALUEPAIR - Displays a key and value pair(like a program indicator) in a given widget.
* HIDEFIELD - Hide a specified dataElement or trackedEntityAttribute.
- content - if defined, the text in content will be displayed to the end user in the instance where a value is previously entered into a field that is now about to be hidden (and therefore blanked). If content is not defined, a standard message will be shown to the user in this instance.
- dataElement - if defined, the HIDEFIELD action will hide this dataElement when the rule is effective.
- trackedEntityDataValue - if defined, the HIDEFIELD action will hide this trackedEntityDataValue when the rule is effective.
* HIDESECTION - Hide a specified section.
- programStageSection - must be defined. This is the programStageSection that will be hidden in case the parent rule is effective.
* ASSIGN - Assign a value to either a dataElement or trackedEntityAttribute or a ProgramRuleVariable. Intended to help the user calculate something or fill in an obvious value somewhere.
- content - if defined, the value in data is assigned to this variable. If content id defined, and thus a variable is assigned for use in other rules, it is important to also assign a programRule.priority to make sure the rule with an ASSIGN action runs before the rule that will in turn evaluate the assigned variable.
- data - must be defined, data forms an expression that is evaluated and assigned to either a variable(#{myVariable}), a dataElement, or both.
- dataElement - if defined, the value in data is assigned to this data element.
Either the content or dataElement must be defined for the ASSIGN action to be effective.
* SHOWWARNING - Show a warning to the user, not blocking the user from completing the event or registration.
- content - if defined, content is a static part that is displayed at the end of the error message.
- data - if defined, data forms an expression that is evaluated and added to the end of the warning message.
- dataElement - if defined, the warning message is displayed next to this data element.
- trackedEntityAttribute - if defined, the warning message is displayed next to this tracked entity attribute.
Either dataElement or trackedEntityAttribute must be specified.
* SHOWERROR - Show an error to the user, blocking the user from completing the event or registration.
- content - if defined, content is a static part that is displayed in the start of the error message.
- data - if defined, data forms an expression that is evaluated and added to the end of the error message.
- dataElement - if defined, the error message is linked to this data element.
- trackedEntityAttribute - if defined, the error message is linked to this tracked entity attribute.
Either dataElement or trackedEntityAttribute must be specified.
* WARNINGONCOMPLETE - Show a warning to the user on the "Complete form" dialog, but allowing the user to complete the event.
- content - if defined, content is a static part that is displayed at the end of the error message.
- data - if defined, data forms an expression that is evaluated and added to the end of the warning message.
- dataElement - if defined, the warning message prefixed with the name/formName of the data element.
* ERRORONCOMPLETE - Show an error to the user on in a modal window when the user tries to complete the event. The user is prevented from completing the event.
- content - if defined, content is a static part that is displayed in the start of the error message.
- data - if defined, data forms an expression that is evaluated and added to the end of the error message.
- dataElement - if defined, the error message is linked to this data element.
* CREATEEVENT - Create an event within the same enrollment.
- content
- data - if defined, contains data values to assign the created event. The format is <uid>:<data value>. Where several values is specified, these are separated with comma.
AcMrnleqHqc:100,AqK1IHqCkEE:'Polyhydramnios'
- programStage - must be defined, and designates the program stage that the rule shall create an event of.
* SETMANDATORYFIELD - Set a field to be mandatory.
- dataElement - if defined, this data element will be set to be mandatory in the data entry form.
- trackedEntityAttribute - if defined, this tracked entity attribute will be set to mandatory in the registration form or profile.
* SENDMESSAGE - To send message at completion of event/enrollment or at data value update.
- messageTemplate - if defined, this template will be delivered either as SMS or EMAIL depending upon DeliveryChannel value in message template.
* SCHEDULEMESSAGE - To schedule message at completion of event/enrollment or at data value update.
- messageTemplate - if defined, this template will be delivered either as SMS or EMAIL depending upon DeliveryChannel value in message template.
- Date to send message - Expression which is going to be used for evaluation of scheduled date. This expression should result in Date, any other resultant will be discarded and notification will not get scheduled.
* HIDEPROGRAMSTAGE - Prevent adding new events to stage.
* HIDEOPTION - Hide option (from an optionSet).
* HIDEOPTIONGROUP - Hide option group (hide the options that belong to that option group).
* SHOWOPTIONGROUP - Show option group (show the options that belong to that option group).
Compulsory
location Used for actionType DISPLAYKEYVALUEPAIR and DISPLAYTEXT to designate which widget to display the text or keyvaluepair in. Compulsory for DISPLAYKEYVALUEPAIR and DISPLAYTEXT. See description
content Used for user messages in the different actions. See the actionType overview for a detailed explanation for how it is used in each of the action types. Compulsory for SHOWWARNING, SHOWERROR, WARNINGONCOMPLETE, ERRORONCOMPLETE, DISPLAYTEXT and DISPLAYKEYVALUEPAIR. Optional for HIDEFIELD and ASSIGN. See description
data Used for expressions in the different actions. See the actionType overview for a detailed explanation for how it is used in each of the action types. Compulsory for ASSIGN. Optional for SHOWWARNING, SHOWERROR, WARNINGONCOMPLETE, ERRORONCOMPLETE, DISPLAYTEXT, CREATEEVENT and DISPLAYKEYVALUEPAIR See description
dataElement Used for linking rule actions to dataElements. See the actionType overview for a detailed explanation for how it is used in each of the action types. Optional for SHOWWARNING, SHOWERROR, WARNINGONCOMPLETE, ERRORONCOMPLETE, ASSIGN and HIDEFIELD See description
trackedEntity- Attribute Used for linking rule actions to trackedEntityAttributes. See the actionType overview for a detailed explanation for how it is used in each of the action types. Optional for SHOWWARNING, SHOWERROR and HIDEFIELD. See description
option Used for linking rule actions to options. See the actionType overview for a detailed explanation for how it is used in each of the action types. Optional for HIDEOPTION See description
optionGroup Used for linking rule actions to optionGroups. See the actionType overview for a detailed explanation for how it is used in each of the action types. Compulsory for SHOWOPTIONGROUP, HIDEOPTIONGROUP. See description
programStage Only used for CREATEEVENT rule actions. Compulsory for CREATEEEVENT. See description
programStage- Section Only used for HIDESECTION rule actions. Compulsory for HIDESECTION See description
ProgramRuleAction Validation

There are certain validations added to ProgramRuleAction model in 2.37. Main purpose was to keep user from creating erroneous ProgramRules in order to keep the database consistent. These validations depends on program rule action type. Each action type has its own respective validation.

ProgramRuleAction Validations
name validation check for id existence
SENDMESSAGE Notification template id
SCHEDULEMESSAGE Notification template id
HIDESECTION ProgramStage section id
HIDEPROGRAMSTAGE ProgramStage id
HIDEFIELD DataElement or TrackedEntityAttribute id
HIDEOPTION Option id
HIDEOPTIONGROUP Option group id
SHOWOPTIONGROUP Option group id
SETMANDATORYFIELD DataElement or TrackedEntityAttribute id
SHOWERROR Always valid
SHOWWARNING Always valid
DISPLAYTEXT DataElement or TrackedEntityAttribute id
DISPLAYKEYVALUEPAIR
ASSIGN DataElement or TrackedEntityAttribute id
WARNINGONCOMPLETE DataElement or TrackedEntityAttribute id
ERRORONCOMPLETE DataElement or TrackedEntityAttribute id

Apart from above validations, data field in program rule action which normally contains expression can also be evaluated using below api endpoint.

POST /api/programRuleActions/data/expression/description?programId=<uid>
{
  "condition": "1 + 1"
}

Program rule variable model details

The following table gives a detailed overview over the programRuleVariable model.

programRuleVariable
name description Compulsory
name the name for the programRuleVariable - this name is used in expressions. #{myVariable} > 5 Compulsory
sourceType Defines how this variable is populated with data from the enrollment and events.
DATAELEMENT_NEWEST_EVENT_PROGRAM_STAGE - This source type works the same way as DATAELEMENT_NEWEST_EVENT_PROGRAM, except that it only evaluates values from one program stage. This source type can be useful in program rules where the same data element is used in several program stages, and a rule needs to evaluate the newest data value from within one specific stage. In order to know what event is the newest, the report date (event date) is used. If you have many events with the same report date, the system choose the one with the latest createdAt property of the event.
DATAELEMENT_NEWEST_EVENT_PROGRAM - This source type is used when a program rule variable needs to reflect the newest known value of a data element, regardless of what event the user currently has open.
**NB
Future dates are "newer" than current or past dates.
In order to know what event is the newest, the report date (event date) is used. If you have many events with the same report date, the system choose the one with the latest createdAt property of the event.
DATAELEMENT_CURRENT_EVENT - Program rule variables with this source type will contain the data value from the same event that the user currently has open. This is the most commonly used source type, especially for skip logic (hide actions) and warning/error rules.
*DATAELEMENT_PREVIOUS_EVENT - Program rule variables with this source type will contain the value from a specified data element from a previous event. Only older events is evaluated, not including the event that the user currently has open. This source type is commonly used when a data element only should be collected once during an enrollment, and should be hidden in subsequent events. Another use case is making rules for validating input where there is an expected progression from one event to the next - a rule can evaluate whether the previous value is higher/lower and give a warning if an unexpected value is entered.
*CALCULATED_VALUE - Program rule variable with this source type is not connected directly to any form data - but will be populated as a result of some other program rules **ASSIGN*
action. This variable will be used for making preliminary calculations, having a ASSIGN program rule action and assigning a value, this value can be used by other program rules - potentially making the expressions simpler and more maintainable. These variables will not be persisted and will stay in memory only during the execution of the set of program rules. Any program rule that assigns a data value to a preliminary calculated value would normally also have a priority assigned - to make sure that the preliminary caculation is done before the rule that consumes the calculated value.
*TEI_ATTRIBUTE - Populates the program rule variable with a specified tracked entity attribute for the current enrollment. Use this is the source type to create program rules that evaluate data values entered during registration. This source type is also useful when you create program rules that compare data in events to data entered during registration. This source type is only used for tracker programs (programs with registration).
Compulsory
valueType valueType parameter defines the type of the value that this ProgramRuleVariable can contain. Its value is dependent on sourceType parameter. If source is DataElement or TrackedEntityAttribute
then valueType will be derived from valueType of the source. When the sourceType is CALCULATED_VALUE, then valueType should be provided by the user otherwise it will default
to ValueType.TEXT
Compulsory
dataElement Used for linking the programRuleVariable to a dataElement. Compulsory for all sourceTypes that starts with DATAELEMENT_. See description
trackedEntity- Attribute Used for linking the programRuleVariable to a trackedEntityAttribute. Compulsory for sourceType TEI_ATTRIBUTE. See description
useCodeFor- OptionSet If checked, the variable will be populated with the code - not the name - from any linked option set. Default is unchecked, meaning that the name of the option is populated.
programStage Used for specifying a specific program stage to retreive the programRuleVariable value from. Compulsory for DATAELEMENT_NEWEST_EVENT_PROGRAM_STAGE. See description

Creating program rules

  • To perform crud operations, programRules resource is available in API.

To retrieve list of programRules you can do a GET request like this:

/api/programRules

To retrieve single programRule you can do a GET request like this:

/api/programRules/<program_rule_uid>

To save/add single programRule you can do a POST request like this:

/api/programRules/<program_rule_uid>

To update single programRule you can do a PUT request like this:

/api/programRules/<program_rule_uid>

To delete single programRule you can do a DELETE request like this:

/api/programRules/<program_rule_uid>

To retrieve description of programRule condition you can use POST and provide condition string in the POST body.

/api/programRules/condition/description?<program_rule_uid>

Forms

To retrieve information about a form (which corresponds to a data set and its sections) you can interact with the form resource. The form response is accessible as XML and JSON and will provide information about each section (group) in the form as well as each field in the sections, including labels and identifiers. By supplying period and organisation unit identifiers the form response will be populated with data values.

Form query parameters
Parameter Option Description
pe ISO period Period for which to populate form data values.
ou UID Organisation unit for which to populate form data values.
metaData false | true Whether to include metadata about each data element of form sections.

To retrieve the form for a data set you can do a GET request like this:

/api/dataSets/<dataset-id>/form.json

To retrieve the form for the data set with identifier "BfMAe6Itzgt" in XML:

/api/dataSets/BfMAe6Itzgt/form

To retrieve the form including metadata in JSON:

/api/dataSets/BfMAe6Itzgt/form.json?metaData=true

To retrieve the form filled with data values for a specific period and organisation unit in XML:

/api/dataSets/BfMAe6Itzgt/form.xml?ou=DiszpKrYNg8&pe=201401

When it comes to custom data entry forms, this resource also allows for creating such forms directly for a data set. This can be done through a POST or PUT request with content type text/html where the payload is the custom form markup such as:

curl -d @form.html "localhost/api/dataSets/BfMAe6Itzgt/form"
  -H "Content-Type:text/html" -u admin:district -X PUT

Documents

References to files can be stored with the document resource.

Document fields
Field name Description
name unique name of document
external flag identifying the location of the document. TRUE for external files, FALSE for internal ones
url the location of the file. URL for external files. File resource id for internal ones (see File resources)

A GET request to the documents endpoint will return all documents:

/api/documents

A POST request to the documents endpoint will create a new document:

curl -X POST -d @document.json -H "Content-type: application/json"
  "http://dhis.domain/api/documents"
{
  "name": "dhis home",
  "external": true,
  "url": "https://www.dhis2.org"
}

A GET request with the id of a document appended will return information about the document. A PUT request to the same endpoint will update the fields of the document:

/api/documents/<documentId>

Appending /data to the GET request will return the actual file content of the document:

/api/documents/<documentId>/data

CSV metadata import

DHIS2 supports import of metadata in the CSV format, such as data elements, organisation units and validation rules. Properties for the various metadata objects are identified based on the column order/column index (see below for details). You can omit non-required object properties/columns, but since the column order is significant, an empty column must be included. In other words, if you would like to specify properties/columns which appear late in the column order but not specify certain columns which appear early in the order you can include empty/blank columns for them.

The first row of the CSV file is considered to be a header and is ignored during import. The comma character should be used as a text delimiter. Text which contains commas must be enclosed in double quotes.

To upload metadata in CSV format you can make a POST request to the metadata endpoint:

POST /api/metadata?classKey=CLASS-KEY

The following object types are supported. The classKey query parameter is mandatory and can be found next to each object type in the table below.

Object types and keys
Object type Class key
عناصر البيانات DATA_ELEMENT
Data element groups DATA_ELEMENT_GROUP
Category options CATEGORY_OPTION
Category option groups CATEGORY_OPTION_GROUP
الوحدات التنظيمية ORGANISATION_UNIT
Organisation unit groups ORGANISATION_UNIT_GROUP
Validation rules VALIDATION_RULE
Option sets OPTION_SET
Translations TRANSLATION

Tip

If using curl, the --data-binary option should be used as it preserves line breaks and newlines, which is essential for CSV data.

As an example, to upload a file of data elements in CSV format with curl you can use the following command:

curl --data-binary @data_elements.csv "http://localhost/api/metadata?classKey=DATA_ELEMENT"
  -H "Content-Type:application/csv" -u admin:district

The formats for the currently supported object types for CSV import are listed in the following sections.

Data elements

Data Element CSV Format
Index Column Required Value (default first) Description
1 Name Yes Name. Max 230 char. Unique.
2 UID No UID Stable identifier. Exactly 11 alpha-numeric characters, beginning with a letter. Will be generated by system if not specified.
3 Code No Stable code. Max 50 char.
4 Short name No 50 first char of name Will fall back to first 50 characters of name if unspecified. Max 50 char. Unique.
5 Description No Free text description.
6 Form name No Max 230 char.
7 Domain type No AGGREGATE | TRACKER Domain type for data element, can be aggregate or tracker. Max 16 char.
8 Value type No INTEGER | NUMBER | UNIT_INTERVAL | PERCENTAGE | INTEGER_POSITIVE | INTEGER_NEGATIVE | INTEGER_ZERO_OR_POSITIVE | FILE_RESOURCE | COORDINATE |TEXT | LONG_TEXT | LETTER | PHONE_NUMBER | EMAIL | BOOLEAN | TRUE_ONLY | DATE | DATETIME Value type. Max 16 char.
9 نوع التجميع No SUM | AVERAGE | AVERAGE_SUM_ORG_UNIT | COUNT | STDDEV | VARIANCE | MIN | MAX | NONE Aggregation type indicating how to aggregate data in various dimensions. Max 16 char.
10 Category combination No UID UID of category combination. Will default to default category combination if not specified.
11 Url No URL to data element resource. Max 255 char.
12 Zero is significant No false | true Indicates whether zero values will be stored for this data element.
13 Option set No UID UID of option set to use for data.
14 Comment option set No UID UID of option set to use for comments.

An example of a CSV file for data elements can be seen below. The first row will always be ignored. Note how you can skip columns and rely on default values to be used by the system. You can also skip columns which you do not use which appear to the right of the ones

name,uid,code,shortname,description
"Women participated skill development training",,"D0001","Women participated in training"
"Women participated community organizations",,"D0002","Women participated in organizations"

Organisation units

Organisation Unit CSV Format
Index Column Required Value (default first) Description
1 Name Yes Name. Max 230 characters. Unique.
2 UID No UID Stable identifier. Max 11 char. Will be generated by system if not specified.
3 Code No Stable code. Max 50 char.
4 Parent No UID UID of parent organisation unit.
5 Short name No 50 first char of name Will fall back to first 50 characters of name if unspecified. Max 50 characters. Unique.
6 Description No Free text description.
7 Opening date No 1970-01-01 Opening date of organisation unit in YYYY-MM-DD format.
8 Closed date No Closed date of organisation unit in YYYY-MM-DD format, skip if currently open.
9 Comment No Free text comment for organisation unit.
10 Feature type No NONE | MULTI_POLYGON | POLYGON | POINT | SYMBOL Geospatial feature type.
11 Coordinates No Coordinates used for geospatial analysis in Geo JSON format.
12 URL No URL to organisation unit resource. Max 255 char.
13 Contact person No Contact person for organisation unit. Max 255 char.
14 العنوان No Address for organisation unit. Max 255 char.
15 Email No Email for organisation unit. Max 150 char.
16 رقم الهاتف No Phone number for organisation unit. Max 150 char.

A minimal example for importing organisation units with a parent unit looks like this:

name,uid,code,parent
"West province",,"WESTP","ImspTQPwCqd"
"East province",,"EASTP","ImspTQPwCqd"

Validation rules

Validation Rule CSV Format
Index Column Required Value (default first) Description
1 Name Yes Name. Max 230 characters. Unique.
2 UID No UID Stable identifier. Max 11 char. Will be generated by system if not specified.
3 Code No Stable code. Max 50
4 Description No Free text description.
5 Instruction No Free text instruction.
6 Importance No MEDIUM | HIGH | LOW Importance of validation rule.
7 Rule type (ignored) No VALIDATION | SURVEILLANCE Type of validation rule.
8 Operator No equal_to | not_equal_to | greater_than | greater_than_or_equal_to | less_than | less_than_or_equal_to | compulsory_pair | exclusive_pair Expression operator.
9 Period type No Monthly | Daily | Weekly | Quarterly | SixMontly | Yearly Period type.
10 Left side expression Yes Mathematical formula based on data element and option combo UIDs.
11 Left side expression description Yes Free text.
12 Left side missing value strategy No SKIP_IF_ANY_VALUE_MISSING | SKIP_IF_ALL_VALUES_MISSING | NEVER_SKIP Behavior in case of missing values in left side expression.
13 Right side expression Yes Mathematical formula based on data element and option combo UIDs.
14 Right side expression description Yes Free text.
15 Right side missing value strategy No SKIP_IF_ANY_VALUE_MISSING | SKIP_IF_ALL_VALUES_MISSING | NEVER_SKIP Behavior in case of missing values in right side expression.

Option sets

Option Set CSV Format
Index Column Required Value (default first) Description
1 OptionSetName Yes Name. Max 230 characters. Unique. Should be repeated for each option.
2 OptionSetUID No UID Stable identifier. Max 11 char. Will be generated by system if not specified. Should be repeated for each option.
3 OptionSetCode No Stable code. Max 50 char. Should be repeated for each option.
4 OptionName Yes Option name. Max 230 characters.
5 OptionUID No UID Stable identifier. Max 11 char. Will be generated by system if not specified.
6 OptionCode Yes Stable code. Max 50 char.

The format for option sets is special. The three first values represent an option set. The three last values represent an option. The first three values representing the option set should be repeated for each option.

optionsetname,optionsetuid,optionsetcode,optionname,optionuid,optioncode
"Color",,"COLOR","Blue",,"BLUE"
"Color",,"COLOR","Green",,"GREEN"
"Color",,"COLOR","Yellow",,"YELLOW"
"Sex",,,"Male",,"MALE"
"Sex",,,"Female",,"FEMALE"
"Sex",,,"Unknown",,"UNKNOWN"
"Result",,,"High",,"HIGH"
"Result",,,"Medium",,"MEDIUM"
"Result",,,"Low",,"LOW"
"Impact","cJ82jd8sd32","IMPACT","Great",,"GREAT"
"Impact","cJ82jd8sd32","IMPACT","Medium",,"MEDIUM"
"Impact","cJ82jd8sd32","IMPACT","Poor",,"POOR"

Option group

Option Group CSV Format
Index Column Required Value (default first) Description
1 OptionGroupName Yes Name. Max 230 characters. Unique. Should be repeated for each option.
2 OptionGroupUid No Stable identifier. Max 11 char. Will be generated by system if not specified. Should be repeated for each option.
3 OptionGroupCode No Stable code. Max 50 char. Should be repeated for each option.
4 OptionGroupShortName Yes Short Name. Max 50 characters. Unique. Should be repeated for each option.
5 OptionSetUid Yes Stable identifier. Max 11 char. Should be repeated for each option.
6 OptionUid No Stable identifier. Max 11 char.
7 OptionCode No Stable code. Max 50 char.

Sample OptionGroup CSV payload

optionGroupName,optionGroupUid,optionGroupCode,optionGroupShortName,optionSetUid,optionUid,optionCode
optionGroupA,,,groupA,xmRubJIhmaK,,OptionA
optionGroupA,,,groupA,xmRubJIhmaK,,OptionB
optionGroupB,,,groupB,QYDAByFgTr1,,OptionC

Option Group Set

Option Group Set CSV Format
Index Column Required Value (default first) Description
1 OptionGroupSetName Yes Name. Max 230 characters. Unique. Should be repeated for each option.
2 OptionGroupSetUid No Stable identifier. Max 11 char. Will be generated by system if not specified. Should be repeated for each option.
3 OptionGroupSetCode No Stable code. Max 50 char. Should be repeated for each option.
4 OptionGroupSetDescription No Description. Should be repeated for each option.
5 DataDimension No TRUE, FALSE
6 OptionSetUid No OptionSet UID. Stable identifier. Max 11 char.

Sample OptionGroupSet CSV payload

name,uid,code,description,datadimension,optionsetuid
optiongroupsetA,,,,,xmRubJIhmaK
optiongroupsetB,,,,false,QYDAByFgTr1
To add OptionGroups to an imported OptionGroupSet, follow the steps as importing collection membership

Indicators

Indicator CSV Format
Index Column Required Value (default first) Description
1 Name Yes Name. Max 230 char. Unique.
2 UID No UID Stable identifier. Exactly 11 alpha-numeric characters, beginning with a letter. Will be generated by system if not specified.
3 Code No Stable code. Max 50 char.
4 Short name Yes 50 first char of name Will fall back to first 50 characters of name if unspecified. Max 50 char. Unique.
5 denominator Yes Indicator expression.
6 denominatorDescription No Max 230 char.
5 numerator Yes Indicator expression.
6 numeratorDescription No Max 230 char.
6 annualized Yes TRUE, FALSE
6 decimals No Number of decimals to use for indicator value, null implies default.
6 Indicator Type Yes UID

An example of a CSV file for Indicators can be seen below. The first row will always be ignored. Note how you can skip columns and rely on default values to be used by the system. You can also skip columns which you do not use which appear to the right of the ones

Name,UID,Code,Description,shortName,denominator,denominatorDescription,numerator,numeratorDescription,annualized,decimals,indicatorType
Indicator A,yiAKjiZVoOU,CodeA,Indicator A description,Indicator A shortname,#{fbfJHSPpUQD},denominatorDescription,#{h0xKKjijTdI},numeratorDescription,false,2,sqGRzCziswD
Indicator B,Uvn6LCg7dVU,CodeB,Indicator B description,Indicator B shortname,#{fbfJHSPpUQD},denominatorDescription,#{h0xKKjijTdI},numeratorDescription,false,2,sqGRzCziswD

Collection membership

In addition to importing objects, you can also choose to only import the group-member relationship between an object and a group. Currently, the following group and object pairs are supported

  • Organisation Unit Group - Organisation Unit

  • Data Element Group - Data Element

  • Indicator Group - Indicator

  • Option Group Set - Option Group

The CSV format for these imports are the same

Collection membership CSV Format
Index Column Required Value (default first) Description
1 UID Yes UID The UID of the collection to add an object to
2 UID Yes UID The UID of the object to add to the collection

Category Option Group

Index Column Required Value (default first) Description
1 Name Yes Name. Max 230 characters. Unique.
2 UID No UID Stable identifier. Max 11 chars. Will be generated by system if not specified.
3 Code No Stable code. Max 50 char.
4 Short name No Short name. Max 50 characters.
5 Data Dimension Type Yes Data Dimension Type, can be either DISAGGREGATION or ATTRIBUTE

Other objects

Data Element Group, Category Option, Organisation Unit Group CSV Format
Index Column Required Value (default first) Description
1 Name Yes Name. Max 230 characters. Unique.
2 UID No UID Stable identifier. Max 11 chars. Will be generated by system if not specified.
3 Code No Stable code. Max 50 char.
4 Short name No Short name. Max 50 characters.

An example of category options looks like this:

name,uid,code,shortname
"Male",,"MALE"
"Female",,"FEMALE"

Deleted objects

The deleted objects resource provides a log of metadata objects being deleted.

/api/deletedObjects

Whenever an object of type metadata is deleted, a log is being kept of the uid, code, the type and the time of when it was deleted. This API is available at /api/deletedObjects field filtering and object filtering works similarly to other metadata resources.

Get deleted objects of type data elements:

GET /api/deletedObjects.json?klass=DataElement

Get deleted object of type indicator which was deleted in 2015 and forward:

GET /api/deletedObjects.json?klass=Indicator&deletedAt=2015-01-01

Favorites

Certain types of metadata objects can be marked as favorites for the currently logged in user. This applies currently for dashboards.

/api/dashboards/<uid>/favorite

To make a dashboard a favorite you can make a POST request (no content type required) to a URL like this:

/api/dashboards/iMnYyBfSxmM/favorite

To remove a dashboard as a favorite you can make a DELETE request using the same URL as above.

The favorite status will appear as a boolean favorite field on the object (e.g. the dashboard) in the metadata response.

Subscriptions

A logged user can subscribe to certain types of objects. Currently subscribable objects are those of type EventChart, EventReport, Map, Visualization and EventVisualization.

Note

The EventChart and EventReport objects are deprecated. Use EventVisualization instead.

To get the subscribers of an object (return an array of user IDs) you can make a GET request:

/api/<object-type>/<object-id>/subscribers

See example as follows:

/api/visualizations/DkPKc1EUmC2/subscribers

To check whether the current user is subscribed to an object (returns a boolean) you can perform a GET call:

/api/<object-type>/<object-id>/subscribed

See example as follows:

/api/visualizations/DkPKc1EUmC2/subscribed

To subscribe/de-subscribe to an object you perform a POST/DELETE request (no content type required):

/api/<object-type>/<object-id>/subscriber

File resources

File resources are objects used to represent and store binary content. The FileResource object itself contains the file meta-data (name, Content-Type, size, etc.) as well as a key allowing retrieval of the contents from a database-external file store. The FileResource object is stored in the database like any other but the content (file) is stored elsewhere and is retrievable using the contained reference (storageKey).

/api/fileResources

The contents of file resources are not directly accessible but are referenced from other objects (such as data values) to store binary content of virtually unlimited size.

To create a file resource that does not require a corresponding data value, POST to the endpoint /api/fileResources with a multipart upload:

curl "https://server/api/fileResources" -X POST
  -F "file=@/path/to/file/name-of-file.png"
The uid of a file resource can be provided when it is created, for example:
curl "https://server/api/fileResources?uid=0123456789x" -X POST
  -F "file=@/path/to/file/name-of-file.png"

To create both a file resource and a data value that references the file, POST to the /api/dataValues/file endpoint in DHIS 2.36 or later:

curl "https://server/api/dataValues/file?de=xPTAT98T2Jd
  &pe=201301&ou=DiszpKrYNg8&co=Prlt0C1RF0s" -X POST
  -F "file=@/path/to/file/name-of-file.png"

For the api/fileResources endpoint, the only form parameter required is file, which is the file to upload. For the api/dataValues/file endpoint, the parameters required are the same as for a post to api/dataValues, with the addition of file.

The filename and content-type should also be included in the request but will be replaced with defaults when not supplied.

On successfully creating a file resource the returned data will contain a response field which in turn contains the fileResource like this:

{
  "httpStatus": "Accepted",
  "httpStatusCode": 202,
  "status": "OK",
  "response": {
    "responseType": "FileResource",
    "fileResource": {
      "name": "name-of-file.png",
      "created": "2015-10-16T16:34:20.654+0000",
      "lastUpdated": "2015-10-16T16:34:20.667+0000",
      "externalAccess": false,
      "publicAccess": "--------",
      "user": { ... },
      "displayName": "name-of-file.png",
      "contentType": "image/png",
      "contentLength": 512571,
      "contentMd5": "4e1fc1c3f999e5aa3228d531e4adde58",
      "storageStatus": "PENDING",
      "id": "xm4JwRwke0i"
    }
  }
}

Note that the response is a 202 Accepted, indicating that the returned resource has been submitted for background processing (persisting to the external file store in this case). Also, note the storageStatus field which indicates whether the contents have been stored or not. At this point, the persistence to the external store is not yet finished (it is likely being uploaded to a cloud-based store somewhere) as seen by the PENDING status.

Even though the content has not been fully stored yet the file resource can now be used, for example as referenced content in a data value (see Working with file data values). If we need to check the updated storageStatus or otherwise retrieve the metadata of the file, the fileResources endpoint can be queried.

curl "https://server/api/fileResources/xm4JwRwke0i" -H "Accept: application/json"

This request will return the FileResource object as seen in the response of the above example.

File resource constraints

  • File resources must be referenced (assigned) from another object in order to be persisted in the long term. A file resource which is created but not referenced by another object such as a data value is considered to be in staging. Any file resources which are in this state and are older than two hours will be marked for deletion and will eventually be purged from the system.

  • The ID returned by the initial creation of the file resource is not retrievable from any other location unless the file resource has been referenced (in which the ID will be stored as the reference), so losing it will require the POST request to be repeated and a new object to be created. The orphaned file resource will be cleaned up automatically.

  • File resource objects are immutable, meaning modification is not allowed and requires creating a completely new resource instead.

File resource blocklist

Certain types of files are blocked from being uploaded for security reasons.

The following content types are blocked.

Content type Content type
text/html application/x-ms-dos-executable
text/css application/vnd.microsoft.portable-executable
text/javascript application/vnd.apple.installer+xml
font/otf application/vnd.mozilla.xul+xml
application/x-shockwave-flash application/x-httpd-php
application/vnd.debian.binary-package application/x-sh
application/x-rpm application/x-csh
application/java-archive

The following file extensions are blocked.

File extension File extension File extension
html deb xul
htm rpm php
css jar bin
js jsp sh
mjs exe csh
otf msi bat
swf mpkg

Metadata versioning

This section explains the metadata versioning APIs.

  • /api/metadata/version: This endpoint will return the current metadata version of the system on which it is invoked.
Query Parameters
Name Required Description
versionName false If this parameter is not specified, it will return the current version of the system or otherwise it will return the details of the versionName passed as parameter. (versionName is of the syntax "Version_<id>"

Get metadata version examples

Example: Get the current metadata version of this system

Request:

/api/metadata/version

Response:

{
  "name": "Version_4",
  "created": "2016-06-30T06:01:28.684+0000",
  "lastUpdated": "2016-06-30T06:01:28.685+0000",
  "externalAccess": false,
  "displayName": "Version_4",
  "type": "BEST_EFFORT",
  "hashCode": "848bf6edbaf4faeb7d1a1169445357b0",
  "id": "Ayz2AEMB6ry"
}

Example: Get the details of version with name "Version_2"

Request:

/api/metadata/version?versionName=Version_2

Response:

{
  "name": "Version_2",
  "created": "2016-06-30T05:59:33.238+0000",
  "lastUpdated": "2016-06-30T05:59:33.239+0000",
  "externalAccess": false,
  "displayName": "Version_2",
  "type": "BEST_EFFORT",
  "hashCode": "8050fb1a604e29d5566675c86d02d10b",
  "id": "SaNyhusVxBG"
}
  • /api/metadata/version/history: This endpoint will return the list of all metadata versions of the system on which it is invoked.
Query Parameters
Name Required Description
baseline false If this parameter is not specified, it will return list of all metadata versions. Otherwise we need to pass a versionName parameter of the form "Version_<id>". It will then return the list of versions present in the system which were created after the version name supplied as the query parameter.

Get the list of all metadata versions

Example: Get the list of all versions in this system

Request:

/api/metadata/version/history

Response:

{
  "metadataversions": [{
    "name": "Version_1",
    "type": "BEST_EFFORT",
    "created": "2016-06-30T05:54:41.139+0000",
    "id": "SjnhUp6r4hG",
    "hashCode": "fd1398ff7ec9fcfd5b59d523c8680798"
  }, {
    "name": "Version_2",
    "type": "BEST_EFFORT",
    "created": "2016-06-30T05:59:33.238+0000",
    "id": "SaNyhusVxBG",
    "hashCode": "8050fb1a604e29d5566675c86d02d10b"
  }, {
    "name": "Version_3",
    "type": "BEST_EFFORT",
    "created": "2016-06-30T06:01:23.680+0000",
    "id": "FVkGzSjAAYg",
    "hashCode": "70b779ea448b0da23d8ae0bd59af6333"
  }]
}

Example: Get the list of all versions in this system created after "Version_2"

Request:

/api/metadata/version/history?baseline=Version_2

Response:

{
  "metadataversions": [{
    "name": "Version_3",
    "type": "BEST_EFFORT",
    "created": "2016-06-30T06:01:23.680+0000",
    "id": "FVkGzSjAAYg",
    "hashCode": "70b779ea448b0da23d8ae0bd59af6333"
  }, {
    "name": "Version_4",
    "type": "BEST_EFFORT",
    "created": "2016-06-30T06:01:28.684+0000",
    "id": "Ayz2AEMB6ry",
    "hashCode": "848bf6edbaf4faeb7d1a1169445357b0"
  }]
 }
  • /api/metadata/version/create: This endpoint will create the metadata version for the version type as specified in the parameter.
Query Parameters
Name Required Description
type true The type of metadata version which needs to be created.
* BEST_EFFORT
* ATOMIC

Users can select the type of metadata which needs to be created. Metadata Version type governs how the importer should treat the given version. This type will be used while importing the metadata. There are two types of metadata.

  • BEST_EFFORT: This type suggests that missing references can be ignored and the importer can continue importing the metadata (e.g. missing data elements on a data element group import).

  • ATOMIC: This type ensures a strict type checking of the metadata references and the metadata import will fail if any of the references do not exist.

Note

It's recommended to have an ATOMIC type of versions to ensure that all systems (central and local) have the same metadata. Any missing reference is caught in the validation phase itself. Please see the importer details for a full explanation.

Create metadata version

Example: Create metadata version of type BEST_EFFORT

Request:

curl -X POST -u admin:district "https://play.dhis2.org/dev/api/metadata/version/create?type=BEST_EFFORT"

Response:

{
  "name": "Version_1",
  "created": "2016-06-30T05:54:41.139+0000",
  "lastUpdated": "2016-06-30T05:54:41.333+0000",
  "externalAccess": false,
  "publicAccess": "--------",
  "user": {
    "name": "John Traore",
    "created": "2013-04-18T17:15:08.407+0000",
    "lastUpdated": "2016-04-06T00:06:06.571+0000",
    "externalAccess": false,
    "displayName": "John Traore",
    "id": "xE7jOejl9FI"
  },
  "displayName": "Version_1",
  "type": "BEST_EFFORT",
  "hashCode": "fd1398ff7ec9fcfd5b59d523c8680798",
  "id": "SjnhUp6r4hG"
}
  • /api/metadata/version/{versionName}/data: This endpoint will download the actual metadata specific to the version name passed as path parameter.

  • /api/metadata/version/{versionName}/data.gz: This endpoint will download the actual metadata specific to the version name passed as path parameter in a compressed format (gzipped).

Path parameters
Name Required Description
versionName true Path parameter of the form "Version_<id>" so that the API downloads the specific version

Download version metadata

Example: Get the actual metadata for "Version 5"

Request:

curl -u admin:district "https://play.dhis2.org/dev/api/metadata/version/Version_5/data"

Response:

{
  "date": "2016-06-30T06:10:23.120+0000",
  "dataElements": [
    {
      "code": "ANC 5th Visit",
      "created": "2016-06-30T06:10:09.870+0000",
      "lastUpdated": "2016-06-30T06:10:09.870+0000",
      "name": "ANC 5th Visit",
      "id": "sCuZKDsix7Y",
      "shortName": "ANC 5th Visit ",
      "aggregationType": "SUM",
      "domainType": "AGGREGATE",
      "zeroIsSignificant": false,
      "valueType": "NUMBER",
      "categoryCombo": {
        "id": "p0KPaWEg3cf"
      },
      "user": {
        "id": "xE7jOejl9FI"
      }
    }
  ]
}

Metadata synchronization

This section explains the Metadata Synchronization API available starting 2.24

  • /api/metadata/sync: This endpoint performs metadata sync of the version name passed in the query parameter by downloading and importing the specified version from the remote server as defined in the settings app.
Query parameters
Name Required Description
versionName true versionName query parameter of the form "Version_<id>" . The api downloads this version from the remote server and imports it in the local system.
  • This API should be used with utmost care. Please note that there is an alternate way to achieve sync in a completely automated manner by leveraging the Metadata Sync Task from the "Data Administration" app. See Chapter 22, Section 22.17 of User Manual for more details regarding Metadata Sync Task.

  • This sync API can alternatively be used to sync metadata for the versions which have failed from the metadata sync scheduler. Due to its dependence on the given metadata version number, care should be taken for the order in which this gets invoked. E.g. If this api is used to sync some higher version from the central instance, then the sync might fail as the metadata dependencies are not present in the local instance.

  • Assume the local instance is at Version_12 and if this endpoint is used to sync Version_15 (of type BEST_EFFORT) from the central instance, the scheduler will start syncing metadata from Version_16. So the local instance will not have the metadata versions between Version_12 and Version_15. You need to manually sync the missing versions using these endpoints only.

Sync metadata version

Example: Sync Version_6 from central system to this system

Request:

curl -u admin:district "https://play.dhis2.org/dev/api/metadata/sync?versionName=Version_6"

Metadata repository

DHIS2 provides a metadata repository containing metadata packages with various content. A metadata package is a DHIS2-compliant JSON document which describes a set of metadata objects.

To retrieve an index over available metadata packages you can issue a GET request to the metadataRepo resource:

GET /api/synchronization/metadataRepo

A metadata package entry contains information about the package and a URL to the relevant package. An index could look like this:

{
  "packages": [
    {
      "id": "sierre-leone-demo",
      "name": "Sierra Leone demo",
      "description": "Sierra Leone demo database",
      "version": "0.1",
      "href": "https://dhis2.org/metadata-repo/221/sierra-leone-demo/metadata.json"
    },
    {
      "id": "trainingland-org-units",
      "name": "Trainingland organisation units",
      "description": "Trainingland organisation units with four levels",
      "version": "0.1",
      "href": "https://dhis2.org/metadata-repo/221/trainingland-org-units/metadata.json"
    }
  ]
}

A client can follow the URLs and install a metadata package through a POST request with content type text/plain with the metadata package URL as the payload to the metadataPull resource:

POST /api/synchronization/metadataPull

An example curl command looks like this:

curl "localhost:8080/api/synchronization/metadataPull" -X POST
  -d "https://dhis2.org/metadata-repo/221/trainingland-org-units/metadata.json"
  -H "Content-Type:text/plain" -u admin:district

Note

The supplied URL will be checked against the config property metadata.sync.remote_servers_allowed in the dhis.conf file. If the base URL is not one of the configured servers allowed then the operation will not be allowed. See failure example below.
Some examples where the config set is metadata.sync.remote_servers_allowed=https://server1.org/,https://server2.org/ - supply https://server1.org/path/to/resource -> this will be accepted - supply https://server2.org/resource/path -> this will be accepted - supply https://oldserver.org/resource/path -> this will be rejected

Sample failure response in JSON format.

 {
  "httpStatus": "Conflict",
  "httpStatusCode": 409,
  "status": "ERROR",
  "message": "Provided URL is not in the remote servers allowed list",
  "errorCode": "E1004"
}

Reference to created by user

Each object created in DHIS2 will have a property named user which is linked to User who created the object.

From version 2.36 we have changed the name of this property to createdBy to avoid confusion.

However, in order to keep the backwards compability, the legacy user property is still included in the payload and works normally as before.

{
  "createdBy": {
      "displayName": "John Kamara",
      "name": "John Kamara",
      "id": "N3PZBUlN8vq",
      "username": "district"
  },
  "user": {
      "displayName": "John Kamara",
      "name": "John Kamara",
      "id": "N3PZBUlN8vq",
      "username": "district"
  }
}

Metadata proposal workflow

The metadata proposal workflow endpoint allows for a workflow of proposing and accepting changes to metadata.

/api/metadata/proposals

Propose a metadata change

A proposal always targets a single metadata object using:

POST /api/metadata/proposals

Depending on the payload the proposal could:

  • Add a new metadata object.
  • Update an existing metadata object references by ID.
  • Remove an existing metadata object referenced by ID.

To propose adding a new metadata object send a JSON payload like the following:

{
  "type": "ADD",
  "target": "ORGANISATION_UNIT",
  "change": {"name":"My Unit", "shortName":"MyOU", "openingDate": "2020-01-01"}
}
The change property contains the same JSON object that could directly be posted to the corresponding endpoint to create the object.

To propose updating an existing metadata object send a JSON payload like in the below example:

{
  "type": "UPDATE",
  "target": "ORGANISATION_UNIT",
  "targetId": "<id>",
  "change": [
    {"op": "replace", "path": "/name", "value": "New name"}
  ]
}
The targetId refers to the object by its ID which should be updated. The change property here contains a JSON patch payload. This is the same patch payload that could be posted to the corresponding endpoint to directly apply the update.

To propose the removal of an existing object send a payload like in the last example:

{
  "type": "REMOVE",
  "target": "ORGANISATION_UNIT",
  "targetId": "<id>"
}
The targetId refers to the object by its ID which should be removed. A free text comment can be added to any type of comment.

Only target type ORGANISATION_UNIT is supported currently.

Accept a metadata change proposal

To accept an open proposal use POST on the proposal resource

POST /api/metadata/proposals/<uid>

When successful the status of the proposal changes to status ACCEPTED. Once accepted the proposal can no longer be rejected.

Should a proposal fail to apply it changes to status NEEDS_UPDATE. The reason field contains a summary of the failures when this information is available.

Oppose a metadata change proposal

If a proposal isn't quite right and needs adjustment this can be indicated by opposing the proposal by sending a PATCH for the proposal resource

PATCH /api/metadata/proposals/<uid>

Optionally a plain text body can be added to this to give a reason why the proposal got opposed.

A opposed proposal must be in state PROPOSED and will change to state NEEDS_UPDATE.

Adjust a metadata change proposal

A proposal in state NEEDS_UPDATE needs to be adjusted before it can be accepted. To adjust the proposal a PUT request is made for the proposal's resource

PUT /api/metadata/proposals/<uid>

Such an adjustment can either be made without a body or with a JSON body containing an object with the updated change and targetId for the adjustment:

{
  "targetId": "<id>",
  "change": ...
}
The JSON type of the change value depends on the proposal type analogous to when a proposal is initially made.

Reject a metadata change proposal

To reject an open proposal use DELETE on the proposal resource

DELETE /api/metadata/proposals/<uid>

This changes the status of the proposal conclusively to REJECTED. No further changes can be made to this proposal. It is kept as a documentation of the events.

List metadata change proposals

All proposals can be listed:

GET /api/metadata/proposals/

The result list can be filtered using the filter parameter. For example, to list only accepted proposals use:

GET /api/metadata/proposals?filter=status:eq:ACCEPTED

Similarly to only show open proposals use:

GET /api/metadata/proposals?filter=status:eq:PROPOSED

Filters can also be applied to any field except change. Supported filter operators are those described in the Gist Metadata API. This also includes property transformers described for Gist API.

List of available fields are:

Field Description
id unique identifier of the proposal
type ADD a new object, UPDATE an existing object, REMOVE an existing object
status PROPOSED (open proposal), ACCEPTED (successful), NEEDS_UPDATE (accepting caused error or opposed), REJECTED
target type of metadata object to add/update/remove; currently only ORGANISATION_UNIT
targetId UID of the updated or removed object, not defined for ADD
createdBy the user that created the proposal
created the date time when the proposal was created
finalisedBy the user that accepted or rejected the proposal
finalised the date time when the proposal changed to a conclusive state of either accepted or rejected
comment optional plain text comment given for the initial proposal
reason optional plain text given when the proposal was opposed or the errors occurring when accepting a proposal failed
change JSON object for ADD proposal, JSON array for UPDATE proposal, nothing for REMOVE proposal

Viewing metadata change proposals

Individual change proposals can be viewed using

GET /api/metadata/proposals/<uid>

The fields parameter can be used to narrow the fields included for the shown object. For example:

GET /api/metadata/proposals/<uid>?fields=id,type,status,change

Metadata Attribute Value Type and validations

Type التحقق من صحتها
TEXT None
LONG_TEXT None
LETTER Value length = 1 AND is a letter
PHONE_NUMBER Validation is based on this regex ^[0-9+\\(\\)#\\.\\s\\/ext-]{6,50}$. Max length is 50.
Examples: +4733987937, (+47) 3398 7937, (47) 3398 7937.123
EMAIL General email format abc@email.com
BOOLEAN true or false
TRUE_ONLY Only accept true
DATE Use format yyyy-MM-dd
DATETIME Use format yyyy-MM-dd HH:mm:ssZ or yyyy-MM-dd'T'HH:mm:ss
TIME Use fornat HH:mm
NUMBER Value must be numberic with max length = 250
UNIT_INTERVAL Value is numeric and inclusive between 0 and 1
PERCENTAGE Value is a number in the inclusive range of 0 to 100
INTEGER Value is an integer
INTEGER_POSITIVE Value is a positive integer
INTEGER_NEGATIVE Value is a negative integer
INTEGER_ZERO_OR_POSITIVE Value is an positive or zero integer
TRACKER_ASSOCIATE None
USERNAME Value is a username of an existing User
COORDINATE None
ORGANISATION_UNIT Value is a valid UID of an existing OrganisationUnit
REFERENCE None
AGE Value is date of birth. Use format as in DATE type.
URL Value is a valid URL
FILE_RESOURCE Value is a valid UID of existing FileResource
IMAGE Value is a valid UID of existing FileResource
GEOJSON Follow GeoJson Specification
MULTI_TEXT None

Copy Program

Introduction

A user will often want to create many Programs which share many of the same characteristics, and instead of having to create a new Program from scratch, it is efficient and beneficial to copy an existing Program and make modifications to it.
A template Program could theoretically be setup as a base to copy from, which may help with the consistency of Program setups also.

API info

Endpoint

POST /api/programs/{uid}/copy

Example with a Program with a UID of Program123a

POST /api/programs/Program123a/copy

Successful response will include the new Program UID and will look like this:

{
    "httpStatus": "Created",
    "httpStatusCode": 201,
    "status": "OK",
    "message": "Program created: 'Program456b'"
}

The response will also contain a Location header with a link to the newly-created Program. e.g. when run locally the Location value would be http://localhost:9090/api/programs/Program456b

Copy options

The API does allow the optional supplying of a custom prefix, which will be prefixed to the following properties.

Object Property Info
Program name Help identify the new Program
ProgramIndicator name Database constraint - needs to be unique
ProgramIndicator shortName Database constraint - needs to be unique

In this example when a custom prefix is supplied, an original Program with a name of My Simple Program would be copied to a new Program with the name my prefix My Simple Program

If no copy options are sent in the API call then the default Copy of prefix will be used for the above properties.
To send a custom prefix just add a HTTP request param prefix like so:

 POST /api/programs/{uid}/copy?prefix=my prefix

Note

The database does have limits for the number of characters allowed for properties. At the time of writing these limits are noted in the table below. Bear these in mind.

Property character limit
name 230
shortName 50

If a property has exceeded its character limit, then an error will be returned like so:

{
    "httpStatus": "Conflict",
    "httpStatusCode": 409,
    "status": "ERROR",
    "message": "ERROR: value too long for type character varying(230)",
    "errorCode": "E1004"
}

If trying to copy a Program that is not found, a response like this will be returned:

{
    "httpStatus": "Not Found",
    "httpStatusCode": 404,
    "status": "ERROR",
    "message": "Program with id {uid} could not be found.",
    "errorCode": "E1005"
}

Authorisation

Authorities

A User will need the following authorities to be able to copy a Program:

  • F_PROGRAM_PUBLIC_ADD
  • F_PROGRAM_INDICATOR_PUBLIC_ADD

Access

A Program needs one of the following states for it to be able to be copied:

  • Public read & write access
  • A specific User to have sharing read & write access
  • A User is part of a UserGroup that has sharing read & write access

If a User does not have the correct permissions, a Forbidden response is returned like so:

{
    "httpStatus": "Forbidden",
    "httpStatusCode": 403,
    "status": "ERROR",
    "message": "You don't have write permissions for Program Program123a",
    "errorCode": "E1006"
}

Points to note

Deep and shallow copy

When a Program is copied, certain properties of the Program need different kinds of copying. It is important to be aware of what has been deep-copied and what has been shallow-copied.
First of all let's explain the difference between deep and shallow copying in this context.

Deep copy

A deep copy in this context means that a completely new instance of a Program or Program property has been created with its own unique identifiers. These include amongst others:

  • id
  • uid

Deep copies of Program properties will all belong to the newly-created Program copy.

Shallow copy

A shallow copy in this context means that an existing Program property will be reused by the newly-created Program or Program property.

Properties that get deep copied

All properties below have been deep copied. Anything not in included in this table means that it has been shallow copied.

Object Property of
Program
ProgramSection Program
ProgramIndicator Program
ProgramRuleVariable Program
ProgramStage Program
ProgramStageSection ProgramStage
ProgramStageSectionDataElement ProgramStage
Enrollment

Note

The following properties have been set as empty as an initial approach. This approach should keep things simple to start off with.

Object Property
ProgramIndicator groups
ProgramStageSection programIndicators
Enrollment events