Events

This block of API calls are used to create, edit or manipulate events. This implies that the actual event types, blueprints and other dependent parts are already configured.

Creating events

In order to create an event a number of tasks has to be done before. Each event has an event type assosiated. The event type defines:

  • who can create - a list of roles allowed to fill in the first section

  • who can own - a list of roles of users who it is targeted at

  • what data it holds - the forms and workflows

For the event to be successfully created it is necessary that the API user can create and it is created for a user (eventOwner field below) can own.

The API is primarily used to create a simple configuration events and to initiate a workflow. It is not a full replacement of the process. The current API limitation is that:

  • only first section can be created

  • if there is a second section it has to be filled in by the timeline owner.

The first step is to retrieve the event type definition so that we can construct the payload:

>>> event_type_id = "known_event_type_id_to_create"
>>> event_type = requests.get('https://api.kaizenep.com/v2/event-types/{}'.format(event_type_id), headers=headers).json()
{
    "_id": "f48e33c1-c306-432e-bc5f-d096789e5da0",
    "_rev": "4-fc8dd78418a82a8066bd5e5fed1be502",
    "versionGroupId": "15180de9-9828-47e8-b5b8-e15d38bf8be8",
    "name": "Log"
    "description": null,
    "ownerRole": [
        "org_fry:trainee"
    ],
    "type": "eventType",
    "changableVisibility": null,
    "state": "published",
    "defaultVisibility": "public",
    "nextVersion": null,
    "version": 1,
    "sections": [
        {
            "fields": [
                {
                    "type": "customField",
                    "_id": "a86f0add-28d4-48bd-8375-e93155d16072",
                    "blueprintType": "string",
                    "name": "Name of procedure"
                },
                {
                    "blueprint": "00731ef0-0989-4e1c-a690-86d37d442fd4",
                    "_id": "1e5bb595-4a9e-4933-9bf6-4ba079bbf0c9",
                    "type": "blueprint"
                }
            ],
            "_id": "4546a330-66ff-4ca7-80ac-9a6b5cd5558a",
            "filledBy": [
                "org_fry:api_access"
            ]
        }
    ],
    "organisation": "org_fry",
    "dates": [
        {
            "action": "published",
            "date": "2020-03-08T15:57:46.190000+00:00",
            "actor": "72d040ab-57a0-45be-b59e-197f42dad7b6"
        }
    ]
}

In order to create the we need to construct the header:

>>> payload = {
    "eventType": "f48e33c1-c306-432e-bc5f-d096789e5da0",
    "section": "4546a330-66ff-4ca7-80ac-9a6b5cd5558a",
    "eventOwner": "username",
    "meta": {
        "startDate": "2020-10-15",
        "endDate": "2020-10-15"
    },
    "data": []
}

and the first section data. To put together the data we need to provide a value for the fields defined for the specific section - at least all the mandatory fields have to be present.

Note

If a field has type of role, relation or blueprint the id specified has to be id of role, relation or blueprint. For all other fields it should be the original field id (field._id from the field definition)

Using the above example, we can extend the above to:

>>> payload = {
    "eventType": "f48e33c1-c306-432e-bc5f-d096789e5da0",
    "section": "4546a330-66ff-4ca7-80ac-9a6b5cd5558a",
    "eventOwner": "username",
    "meta": {
        "startDate": "2020-10-15",
        "endDate": "2020-10-15"
    },
    "data": [
        {
            "id": "a86f0add-28d4-48bd-8375-e93155d16072",
            "value": "Endoscopy"
        },
        {
            "id": "00731ef0-0989-4e1c-a690-86d37d442fd4",
            "value": "c2520b1b-e5d2-4b48-9989-7db225c6817f"
        }
    ]
}

Now we can create the event:

>>> response = requests.post('https://api.kaizenep.com/v2/events', json=payload, headers=headers)
>>> response.json()
{"id": "new_event_id", "rev": "revision number"}

At this moment a new completed event is visible on the user’s timeline and a notifying email is sent out.

Retrieving an event

When the event is created it can be fetched using a GET request:

>>> response = requests.get('https://api.kaizenep.com/v2/events/182503b1-5fdf-400b-99da-e564b932b66b?includeParts=sections', headers=headers)
>>> response.json()
{
    "id": "182503b1-5fdf-400b-99da-e564b932b66b",
    "rev": "1-1544c709cd5f1c55275785f6296473b0",
    "startDate": "2020-10-02",
    "endDate": "2020-10-02",
    "eventType": {
        "versionGroupId": "15180de9-9828-47e8-b5b8-e15d38bf8be8",
        "version": "1",
        "id": "f48e33c1-c306-432e-bc5f-d096789e5da0",
        "name": "Log"
    },
    "organisation": "org_fry",
    "visibility": "public",
    "state": "complete",
    "user": "fry",
    "type": "event",
    "createdDate": "2020-10-02",
    "progress": {
        "comment": "Completed",
        "value": 100
    },
    "sections": [
        {
            "state": "complete",
            "id": "4546a330-66ff-4ca7-80ac-9a6b5cd5558a",
            "publishedAt": "2020-10-02T13:35:49.476207+00:00",
            "responses": [
                {
                "eventSectionId": "e6560967-f502-4f39-a689-9d43a0b74f44",
                "fields": [
                    {
                        "text_value": "Endoscopy",
                        "type": "string",
                        "key": "a86f0add-28d4-48bd-8375-e93155d16072",
                        "label": "Name of procedure"
                    },
                    {
                        "text_value": "Retrospective",
                        "type": "blueprint",
                        "key": "00731ef0-0989-4e1c-a690-86d37d442fd4",
                        "str_value": "c2520b1b-e5d2-4b48-9989-7db225c6817f",
                        "label": "Log type"
                    }

                ],
                "state": "complete",
                "publishedAt": "2020-10-02T13:35:49.445396+00:00",
                "filledBy": "fry"
                }
            ]
        }
    ],
    "auditLog": [
        {
        "action": "section_publish",
        "date": "2020-10-02T13:35:49.470896+00:00",
        "actor": "fry"
        }
    ],
    "relations": [
        {
            "text_value": "ST1",
            "key": "28423c62-b95d-4de0-907c-5adbbac13e6e",
            "label": "Grades"
        }
    ]
}

The content of a received event can be controlled by a includeParts argument. These are the possible parts:

  • all - Includes everything

  • sections - Includes actual form data

  • featured - Includes only fields marked as Shown on timelines

  • blueprints - Includes consolidated list of blueprints including extra tags

  • relatinos - Includes user relation at the time of the event

  • documents - Includes information about documents attached to the events

  • auditLog - Includes audit log of actions

  • comments - Includes comments on the event

Updating an event

Once an event has been completed it is possible to edit it. It needs to be taken into consideration that an event can have multiple sections and even multiple response to an individual sections. The update API call is designed so that the metadata and multiple responses can be modified.

While it is possible to apply multiple changes at the same time it is possible as well to run it multiple times. For simplicity the examples would be separated.

Updating metadata (dates, description and visibility) is done through a simple call:

>>> payload = {
        "id": "182503b1-5fdf-400b-99da-e564b932b66b",
        "rev": "revision_number",
        "meta": {
            "startDate": "2020-10-16",
            "endDate": "2020-10-16",
            "description": "A new description",
            "visibility": "private"
        }
    }
>>> response = requests.put('https://api.kaizenep.com/v2/events/182503b1-5fdf-400b-99da-e564b932b66b?includeParts=sections', headers=headers)
>>> response.json()
{"id": "182503b1-5fdf-400b-99da-e564b932b66b", "rev": "2-new revision number"}

To update a specific section data the responses field has to be used. To identify a response it is enough to enter relevant section id if it is not a multi source feedback section. In case of a multi source feedback an additional response identifier has to be added - eventSectionId - which is an id of a form submitted by the participant.

>>> payload = {
        "id": "182503b1-5fdf-400b-99da-e564b932b66b",
        "rev": "revision_number",
        "responses": [
            {
                "id": "4546a330-66ff-4ca7-80ac-9a6b5cd5558a",
                "data": [
                    {
                        "id": "a86f0add-28d4-48bd-8375-e93155d16072",
                        "value": "Lumbar puncture"
                    },
                    {
                        "id": "00731ef0-0989-4e1c-a690-86d37d442fd4",
                        "value": "c2520b1b-e5d2-4b48-9989-7db225c6817f"
                    }
                ]
            }
        ]
    }
>>> response = requests.put('https://api.kaizenep.com/v2/events/182503b1-5fdf-400b-99da-e564b932b66b?includeParts=sections', headers=headers)
>>> response.json()
{"id": "182503b1-5fdf-400b-99da-e564b932b66b", "rev": "3-new revision number"}

Searching for events

Searching for events is done by sending a POST request to the search endpoint. The actual search is controlled by the payload which consts of these parts (all are optional):

  • filter - This defines the filter applied. For a complete list of available options please look at the OpenApi specification. This does not have and defaults so omitting all filters means it returns everyone.

  • sort - This defines how the results are sorted. Please have a look at the specification which sortings are available

  • size - This defines how many rows should be returned. At the moment there is no hard limit. The recommended size depends on requested data being returned. If full objects are being returned the size should be less than 1000.

  • start - This defines the offset when search allowing for pagination.

  • options This controls whether it returns only user ids or the full objects. If the full objects are returned is it possible to further limit the content using the includeParts as when retrieving one user.

An example request returning only ids:

>>> payload = {
        "filter": {
            "state": ["complete"],
            "after": "2020-01-01"
        },
        "size": 10,
        "options": {
            "includeIds": true,
            "includeDocs": false
            "includeParts": []
        }
    }
>>> response = requests.post('https://api.kaizenep.com/v2/events/search', json=payload, headers=headers)
>>> response.json()
{
    'ids': [
        'd84ab1e9-b453-4928-8877-66a4f596a911',
        '660ad117-01b7-4c61-807c-a418093013ad',
        'e5dca22e-64dd-4a97-b827-27b47111cf58',
        '8ed2827f-9eeb-43d4-8024-79be7f8b273c',
        '74a559a6-d248-4761-bd4e-d678fc893948',
        '28611379-80ba-4d45-806a-139abc5ef85f',
        'b9a46329-fed4-4208-a2ed-429d344b1487',
        '72d040ab-57a0-45be-b59e-197f42dad7b6',
        '509afaea-5d2e-46d6-ae44-c415b0301f22'
    ],
    'size': 10,
    'start': 0,
    'total': 490
}

An example request returning evaluated events:

>>> payload = {
        "filter": {
            "state": ["complete"],
            "after": "2020-01-01"
        },,
        "size": 10,
        "options": {
            "includeIds": false,
            "includeDocs": true
            "includeParts": []
        }
    }
>>> response = requests.post('https://api.kaizenep.com/v2/events/search', json=payload, headers=headers)
>>> response.json()
{
    "docs": [
        {
            "startDate": "2020-10-02",
            "endDate": "2020-10-02",
            "eventType": {
                "versionGroupId": "15180de9-9828-47e8-b5b8-e15d38bf8be8",
                "version": "1",
                "id": "f48e33c1-c306-432e-bc5f-d096789e5da0",
                "name": "Log"
            },
            "organisation": "org_fry",
            "rev": "1-1544c709cd5f1c55275785f6296473b0",
            "visibility": "public",
            "state": "complete",
            "user": "fry",
            "createdDate": "2020-10-02",
            "progress": {
                "comment": "Completed",
                "value": 100
            },
            "type": "event",
            "id": "182503b1-5fdf-400b-99da-e564b932b66b"
        },
        ...
    ],
    'size': 10,
    'start': 0,
    'total': 490
}

When there is a set of known event ids it is possible to retrieve them in bulk using the fetch method:

>>> payload = {
        "ids": [
            'd84ab1e9-b453-4928-8877-66a4f596a911',
            '660ad117-01b7-4c61-807c-a418093013ad',
            'e5dca22e-64dd-4a97-b827-27b47111cf58',
            '8ed2827f-9eeb-43d4-8024-79be7f8b273c',
            '74a559a6-d248-4761-bd4e-d678fc893948',
            '28611379-80ba-4d45-806a-139abc5ef85f',
            'b9a46329-fed4-4208-a2ed-429d344b1487',
            '72d040ab-57a0-45be-b59e-197f42dad7b6',
            '509afaea-5d2e-46d6-ae44-c415b0301f22'
        ],
        "options": {
            "includeParts": []
        }
    }
>>> response = requests.post('https://api.kaizenep.com/v2/events/fetch', json=payload, headers=headers)
>>> response.json()
{
    'docs': [
        {
            "startDate": "2020-10-02",
            "endDate": "2020-10-02",
            "eventType": {
                "versionGroupId": "15180de9-9828-47e8-b5b8-e15d38bf8be8",
                "version": "1",
                "id": "f48e33c1-c306-432e-bc5f-d096789e5da0",
                "name": "Log"
            },
            "organisation": "org_fry",
            "rev": "1-1544c709cd5f1c55275785f6296473b0",
            "visibility": "public",
            "state": "complete",
            "user": "fry",
            "createdDate": "2020-10-02",
            "progress": {
                "comment": "Completed",
                "value": 100
            },
            "type": "event",
            "id": "182503b1-5fdf-400b-99da-e564b932b66b"
        },
        ...
    ]
}

Hint

Best practices

When retrieving large set of data it is recommended to separate the search and fetch into multiple calls. First run the search and let it return the ids - if only ids are returned the size can be in thousands. Next paginate the resulting ids and fetch evaulated objects iteratively. This ensures a fixed result set, faster responses and ability to meausre progress.