Entities

Entities allow you to share information between forms, enabling the collection of longitudinal data, management of cases over time, and support for other complex workflows.

The following endpoints provides access to Entities related data.

Where:

  • Entity - Each item that gets managed by an ODK workflow. Entities are automatically created from submissions received from a form that contains entity definitions.

  • EntityList - a dataset that contains Entities of the same type.

  • entity_list_id - An EntityList’s unique identifier

  • entity_id - An Entity’s unique identifier

Create EntityList

POST /api/v2/entity-lists

This endpoint is used to create a single EntityList dataset within a project. Entities for the dataset can then be created from a form or via the API.

EntityList name must not include . or start with __

EntityList name is unique per project.

The EntityList by default has no properties. See Create EntityList Property to add properties.

Example

curl -X POST "https://api.ona.io/api/v2/entity-lists" \
-H "Authorization: Token ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
         "name": "trees",
         "project": "2",
   }'

Response

Status: 201 Created

Body:

{
   "id":1,
   "name":"trees",
   "project":2,
   "date_created":"2024-06-27T07:35:53.451077Z",
   "date_modified":"2024-06-27T07:35:53.451091Z"
}

Get a list of EntityLists

GET /api/v2/entity-lists

This endpoint is used to get all EntityList datasets.

The user must have view permission for each dataset.

The maximum number of items returned is 1000. To get more results than this, pagination is required. Refer to getting paginated results section.

Example

curl -X GET https://api.ona.io/api/v2/entity-lists

Response

Status: 200 OK

Body:

[
   {
      "url":"http://testserver/api/v2/entity-lists/9",
      "id":9,
      "name":"trees",
      "project":"http://testserver/api/v1/projects/9",
      "public":false,
      "datecreated":"2024-04-17T11:26:24.630117Z",
      "datemodified":"2024-04-17T11:26:25.050823Z",
      "numregistrationforms":1,
      "numfollowupforms":1,
      "numentities":1
   }
]

Get a list of Entities for a specific project

GET /api/v2/entity-lists?project=<project_id>

Example

curl -X GET https://api.ona.io/api/v2/entity-lists?project=9

Response

Status: 200 OK

Body:

[
   {
      "url":"http://testserver/api/v2/entity-lists/9",
      "id":9,
      "name":"trees",
      "project":"http://testserver/api/v1/projects/9",
      "public":false,
      "datecreated":"2024-04-17T11:26:24.630117Z",
      "datemodified":"2024-04-17T11:26:25.050823Z",
      "numregistrationforms":1,
      "numfollowupforms":1,
      "numentities":1
   }
]

Get a paginated list of EntityLists

GET /api/v2/entity-lists?page=<page>&page_size=<page_size>

Returns a list of projects using page number and the number of items per page. Use the page parameter to specify page number and page_size parameter is used to set the custom page size.

  • page - Integer representing the page.

  • page_size - Integer representing the number of records that should be returned in a single page. The maximum number of items that can be requested in a page via the page_size query param is 10,000.

Example

curl -X GET https://api.ona.io/api/v2/entity-lists?page=1&page_size=100

Response

Status: 200 OK

Body:

[
   {
      "url":"http://testserver/api/v2/entity-lists/9",
      "id":9,
      "name":"trees",
      "project":"http://testserver/api/v1/projects/9",
      "public":false,
      "datecreated":"2024-04-17T11:26:24.630117Z",
      "datemodified":"2024-04-17T11:26:25.050823Z",
      "numregistrationforms":1,
      "numfollowupforms":1,
      "numentities":1
   }

]

Get EntityList Details

GET /api/v2/entity-lists/<entity_list_id>

This endpoint is used to get a single EntityList.

Example

curl -X GET https://api.ona.io/api/v2/entity-lists/1

Response

Status: 200 OK

Body:

{
   "id":16,
   "name":"trees",
   "project":"http://testserver/api/v1/projects/13",
   "public":false,
   "date_created":"2024-04-17T11:43:08.530848Z",
   "date_modified":"2024-04-17T11:43:09.030105Z",
   "num_registration_forms":1,
   "num_follow_up_forms":1,
   "num_entities":1,
   "registration_forms":[
      {
         "title":"Trees registration",
         "xform":"http://testserver/api/v1/forms/15",
         "id_string":"trees_registration",
         "save_to":[
            "geometry",
            "species",
            "circumference_cm"
         ]
      }
   ],
   "follow_up_forms":[
      {
         "title":"Trees follow-up",
         "xform":"http://testserver/api/v1/forms/16",
         "id_string":"trees_follow_up"
      }
   ]
}

Download EntityList

GET api/v2/entity-lists/<entity_list_id>/download

or

GET api/v2/entity-lists/<entity_list_id>.csv

This endpoints are used to download the dataset in CSV format.

Example

curl -X GET https://api.ona.io/api/v2/entity-lists/1/download \
-H "Authorization: Token ACCESS_TOKEN"

Response

Status: 200 OK

Delete EntityList

DELETE api/v2/entity-lists/<entity_list_id>

This endpoint is used to delete a single EntityList dataset.

Example

curl -X DELETE https://api.ona.io/api/v2/entity-lists/1 \
-H "Authorization: Token ACCESS_TOKEN"

Response

Status: 204 No Content

Create EntityList Property

POST /api/v2/entity-lists/<entity_list_id>/properties

This endpoint is used to create a property for an EntityList dataset. Properties define the fields that can be used when creating or updating Entities in the dataset.

The following validation rules apply to property names:

  • Property name must not start with __ (reserved prefix)

  • Property name cannot be name or label (reserved names)

  • Property name must be unique per EntityList (case-sensitive)

Example

curl -X POST "https://api.ona.io/api/v2/entity-lists/1/properties" \
-H "Authorization: Token ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
         "name": "height_cm"
   }'

Response

Status: 201 Created

Body:

{
   "name": "height_cm",
   "entity_list": 1
}

Get a list of Entities

GET api/v2/entity-lists/<entity_list_id>/entities

This endpoint is used to get Entities belonging to a single EntityList dataset.

The maximum number of items returned is 1000. To get more results than this, pagination is required. Refer to getting paginated results section.

Example

curl -X GET https://api.ona.io/api/v2/entity-lists/1/entities

Response

Status: 200 OK

Body:

[
   {
      "url":"http://testserver/api/v2/entity-lists/1/entities/3",
      "id":3,
      "uuid": "dbee4c32-a922-451c-9df7-42f40bf78f48",
      "date_created": "2024-06-20T07:37:20.416054Z",
      "data": {
         "species":"purpleheart",
         "geometry":"-1.286905 36.772845 0 0",
         "circumference_cm":300,
         "label":"300cm purpleheart",
      }
   },
   {
      "url":"http://testserver/api/v2/entity-lists/1/entities/4",
      "id":4,
      "uuid": "517185b4-bc06-450c-a6ce-44605dec5480",
      "date_created": "2024-06-20T07:38:20.416054Z",
      "data": {
         "species":"wallaba",
         "geometry":"-1.305796 36.791849 0 0",
         "intake_notes":"Looks malnourished",
         "circumference_cm":100,
         "label":"100cm wallaba",
      }
   }
]

Get a paginated list of Entities

GET /api/v2/entity-lists/1/entities?page=<page>&page_size=<page_size>

Returns a list of projects using page number and the number of items per page. Use the page parameter to specify page number and page_size parameter is used to set the custom page size.

  • page - Integer representing the page.

  • page_size - Integer representing the number of records that should be returned in a single page. The maximum number of items that can be requested in a page via the page_size query param is 10,000.

Example

curl -X GET https://api.ona.io/api/v2/entity-lists/1/entities?page=1&page_size=100

Response

Status: 200 OK

Body:

[
   {
      "url":"http://testserver/api/v2/entity-lists/1/entities/3",
      "id":3,
      "uuid": "dbee4c32-a922-451c-9df7-42f40bf78f48",
      "date_created": "2024-06-20T07:37:20.416054Z",
      "data": {
         "species":"purpleheart",
         "geometry":"-1.286905 36.772845 0 0",
         "circumference_cm":300,
         "label":"300cm purpleheart",
      }
   }
]

Search a list of Entities

GET /api/v2/entity-lists/1/entities?search=<search_term>

Limit list of Entities to those whose data partially matches the provided search term.

Matches are case insensitive.

Example

curl -X GET https://api.ona.io/api/v2/entity-lists/1/entities?search=wallaba

Response

Status: 200 OK

Body:

[
   {
      "url":"http://testserver/api/v2/entity-lists/1/entities/4",
      "id":4,
      "uuid": "517185b4-bc06-450c-a6ce-44605dec5480",
      "date_created": "2024-06-20T07:38:20.416054Z",
      "data": {
         "species":"wallaba",
         "geometry":"-1.305796 36.791849 0 0",
         "intake_notes":"Looks malnourished",
         "circumference_cm":100,
         "label":"100cm wallaba",
      }
   }
]

Create Entity

POST /api/v2/entity-lists/1/entities

This endpoint is used for creating a single Entity in the Entity List.

Note

The EntityList must have properties defined before you can create Entities. If the EntityList has no properties, the request will fail with:

  • Status: 400 Bad Request

  • Body: {"error": "EntityList has no properties defined"}

The data is passed as JSON in the request body. The following keys are available:

  • label - A user-friendly label for forms that use Entities.

  • data - An object with values for user-defined Dataset properties. (Not all properties need to have values.). A property must exist in the EntityList dataset.

  • uuid (optional) - A unique ID. If not provided, one will be generated for the Entity upon creation. The uuid is unique per Entity List.

All property values are of type string.

Example

curl -X POST https://api.ona.io/api/v2/entity-lists/1/entities \
-H "Authorization: Token ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
      "label": "30cm mora",
      "uuid": "dbee4c32-a922-451c-9df7-42f40bf78f48",
      "data": {
            "geometry": "-1.286805 36.772845 0 0",
            "species": "mora",
            "circumference_cm": "30"
      }
   }'

Response

Status: 201 Created

Body:

{
   "id": 1,
   "uuid": "dbee4c32-a922-451c-9df7-42f40bf78f48",
   "date_created": "2024-06-20T07:37:20.416054Z",
   "date_modified": "2024-06-20T08:37:20.416054Z",
   "data": {
      "geometry": "-1.286805 36.772845 0 0",
      "species": "mora",
      "circumference_cm": "30",
      "label": "30cm mora",
   }
}

Get Entity Details

GET api/v2/entity-lists/<entity_list_id>/entities/<entity_id>

This endpoint is used to get a single Entity.

Example

curl -X GET https://api.ona.io/api/v2/entity-lists/1/entities/3

Response

Status: 200 OK

Body:

{
   "id":3,
   "uuid": "dbee4c32-a922-451c-9df7-42f40bf78f48",
   "date_created": "2024-06-20T07:37:20.416054Z",
   "date_modified": "2024-06-20T07:37:20.416054Z",
   "data": {
      "species":"purpleheart",
      "geometry":"-1.286905 36.772845 0 0",
      "circumference_cm":300,
      "label":"300cm purpleheart",
   }
}

Update Entity

PATCH api/v2/entity-lists/<entity_list_id>/entities/<entity_id>

This endpoint is used to update the label or the properties (passed as JSON in the request body) of an Entity.

You only need to include the properties you wish to update. To unset the value of any property, you can set it to empty string (“”).

A property must exist in the EntityList dataset.

The label must be a non-empty string.

The uuid is unique per Entity List.

Example

curl -X PATCH https://api.ona.io/api/v2/entity-lists/1/entities/1 \
-H "Authorization: Token ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
      "label": "30cm mora",
      "data": {
            "geometry": "-1.286805 36.772845 0 0",
            "species": "mora",
            "circumference_cm": "30"
      }
   }'

Response

Status: 200 OK

Body:

{
   "id": 1,
   "uuid": "dbee4c32-a922-451c-9df7-42f40bf78f48",
   "date_created": "2024-06-20T07:37:20.416054Z",
   "date_modified": "2024-06-20T08:37:20.416054Z",
   "data": {
      "geometry": "-1.286805 36.772845 0 0",
      "species": "mora",
      "circumference_cm": "30",
      "label": "30cm mora",
   }
}

Delete Entity

DELETE api/v2/entity-lists/<entity_list_id>/entities

The endpoint is used to delete a single Entity or multiple Entities. The IDs of Entities to be deleted are specified with a JSON payload like this:

{
   "entity_ids": [1, 2, 3]
}

entity_ids must be provided and cannot be an empty list. The items in the list must be valid IDs of Entities that are in the EntityList.

Example

curl -X DELETE https://api.ona.io/api/v2/entity-lists/1/entities \
-H "Authorization: Token ACCESS_TOKEN"
-d '{
      "entity_ids": [1, 2, 3]
   }'

Response

Status: 204 No Content

Import Entities from CSV

POST /api/v2/entity-lists/<entity_list_id>/import-entities

This endpoint is used to import multiple entities from a CSV file into an EntityList dataset. The import process is asynchronous and returns a task ID that can be used to check the import status.

The CSV file must contain columns that match the properties defined in the EntityList dataset. The following parameters are supported:

  • csv_file - The CSV file to import (required)

  • label_column - The name of the column containing entity labels (optional, defaults to “label”)

  • uuid_column - The name of the column containing entity UUIDs (optional, defaults to “uuid”)

CSV File Requirements:

  • Must be a valid CSV file with .csv extension

  • First row should contain column headers

  • UUID column values must be unique within the EntityList

  • Label column values must be non-empty strings

Note

The EntityList must have properties defined before you can import Entities. If the EntityList has no properties, the import request will fail with:

  • Status: 400 Bad Request

  • Body: {"error": "EntityList has no properties defined"}

Example

curl -X POST https://api.ona.io/api/v2/entity-lists/1/import-entities \
-H "Authorization: Token ACCESS_TOKEN" \
-F "csv_file=@trees.csv" \
-F "label_column=label" \
-F "uuid_column=uuid"

CSV File Content Example (trees.csv):

label,species,circumference_cm,uuid
300cm purpleheart,purpleheart,300,dbee4c32-a922-451c-9df7-42f40bf78f48
200cm mora,mora,200,517185b4-bc06-450c-a6ce-44605dec5480
100cm wallaba,wallaba,100,8f2e1a3b-9c4d-4e5f-8a7b-1c2d3e4f5a6b

Response

Status: 202 Accepted

Body:

{
   "task_id": "2335468b-646d-4831-b874-028431c1d339"
}

Check Import Status

GET /api/v2/entity-lists/<entity_list_id>/import-entities?task_id=<task_id>

This endpoint is used to check the status of an ongoing CSV import operation. Use the task_id returned from the import request to monitor progress.

Parameters:

  • task_id - The task ID returned from the import request (required)

Example

curl -X GET https://api.ona.io/api/v2/entity-lists/1/import-entities?task_id=2335468b-646d-4831-b874-028431c1d339 \
-H "Authorization: Token ACCESS_TOKEN"

Response

Status: 200 OK

Body:

   {
   "task_id": "d7b1e80b",
   "state": "SUCCESS",
   "result": {
      "processed": 325,
      "created": 300,
      "updated": 25,
      "errors": []
   }
}

Task States

The import status endpoint returns different states depending on the progress of the import operation:

  • PENDING - Task is queued but not yet started

  • STARTED - Task has begun processing

  • PROGRESS - Task is actively processing rows

  • SUCCESS - Task completed successfully

  • FAILURE - Task failed with an error

  • RETRY - Task is being retried due to a temporary error

Error Handling

When the import task fails, the response will include error details:

CSV Validation Errors (400 Bad Request)

When CSV validation fails, the response includes specific error messages:

{
   "task_id": "d7b1e80b",
   "state": "FAILURE",
   "result": {
      "error": "CSV must include a 'label' column."
   }
}

Common CSV validation errors include:

  • Missing required columns (label column)

  • Invalid CSV format

  • Empty label values

  • Duplicate UUIDs within the CSV

  • Invalid property values

General Import Errors (500 Internal Server Error)

For other types of failures (database errors, connection issues, etc.):

{
   "task_id": "d7b1e80b",
   "state": "FAILURE",
   "result": {
      "error": "The job failed. Please try again."
   }
}

Row-Level Errors

Even when the overall import succeeds, individual rows may have errors. These are included in the success response:

{
   "task_id": "d7b1e80b",
   "state": "SUCCESS",
   "result": {
      "processed": 325,
      "created": 322,
      "updated": 0,
      "errors": [
         [4, "Invalid UUID format"],
         [7, "Label cannot be empty"],
         [12, "Property 'species' is required"]
      ]
   }
}

The errors array contains tuples of [row_number, error_message] for rows that failed to import. Row numbers start from 2 (accounting for the header row). Only the first 50 errors are included in the response.