Overview
kbtbr is a wrapper for the KoBoToolbox APIs. It focuses on API v2 but also makes use of v1 if required.
kbtbr uses R6 classes. This means it has an object-oriented user interface which might feel unfamiliar to R users at first. But don’t worry - you should get used to it quickly!
Setup
Authentication
Get an API token using any of the methods described in the KoBoToolbox documentation. Then store it as an environment variable by opening and editing your .Renviron
:
usethis::edit_r_environ()
Add your token on a new line as follows:
KBTBR_TOKEN=yourapitokenhere
Save the file and restart R/RStudio.
Of course, you can also use local environment files or any other method to securely store the API token.
Base URL
In order to use kbtbr, you need to know the base URLs of your KoBoToolbox server (cf. here). There are two base URLs, one for API version 2 and one for version 1. To use the kbtbr package, you only need to specify the base URL for version 2. However, certain functionalities that rely on the version 1 API will require its base URL.
If you are using one of the two hosted instances, those are the base URLs:
version | Humanitarian Server (OCHA) | Non-Humanitarian Server |
---|---|---|
v2 | https://kobo.humanitarianresponse.info | https://kf.kobotoolbox.org |
v1 | https://kc.humanitarianresponse.info | https://kc.kobotoolbox.org |
Creating the Kobo instance
With the right base URL(s), we can create an instance of the Kobo
class. The base_url_v1
argument is optional.
library(kbtbr)
library(dplyr)
base_url_v2 <- "https://kobo.correlaid.org" # replace with your base URL for v2
base_url_v1 <- "https://kc.correlaid.org" # replace with your base URL for v1
token <- Sys.getenv("KBTBR_TOKEN")
kobo <- Kobo$new(base_url_v2, base_url_v1, token)
kobo
## <Kobo>
## Public:
## clone: function (deep = FALSE)
## clone_asset: function (clone_from, new_name, asset_type)
## create_asset: function (name, asset_type, description = "", sector = list(label = "",
## deploy_asset: function (uid)
## get: function (path, query = list(), version = "v2", format = "json",
## get_asset: function (id)
## get_assets: function ()
## get_submissions: function (id)
## get_surveys: function (show_all_cols = FALSE)
## import_xls_form: function (name, file_path)
## initialize: function (base_url_v2 = NULL, base_url_v1 = NULL, kobo_token = Sys.getenv("KBTBR_TOKEN"),
## post: function (path, body, version = "v2")
## session_v1: KoboClient, HttpClient, R6
## session_v2: KoboClient, HttpClient, R6
For alternative ways of initializing the Kobo
class, see here.
Working with the Kobo class
A good first step is to get an overview over all your assets. Almost everything in KoBoToolbox is an asset: questions, blocks, forms, templates.
assets <- kobo$get_assets()
table(assets$asset_type)
##
## block question survey template
## 9 4 45 7
You can also just get your forms/surveys:
surveys <- kobo$get_surveys()
Inspect the data manually:
head(surveys)
## # A tibble: 6 × 9
## name uid date_created date_modified owner__username parent has_deployment
## <chr> <chr> <chr> <chr> <chr> <chr> <lgl>
## 1 Test s… a27V… 2022-01-24T… 2022-01-24T1… api_user NA TRUE
## 2 Test s… aCZ7… 2022-01-24T… 2022-01-24T1… api_user NA TRUE
## 3 Test s… aXDf… 2022-01-24T… 2022-01-24T1… api_user NA FALSE
## 4 Test s… apwD… 2022-01-24T… 2022-01-24T1… api_user NA FALSE
## 5 clonin… aXLR… 2022-01-24T… 2022-01-24T1… api_user NA FALSE
## 6 kbtbr … aRo4… 2021-05-02T… 2021-09-24T1… api_user NA TRUE
## # … with 2 more variables: deployment__active <lgl>,
## # deployment__submission_count <int>
You can then extract the ID of a single survey by filtering for its name.
Get the answers (or submissions in KoBoToolbox API lingo) to the form/survey:
submissions <- kobo$get_submissions(test_id)
str(submissions)
## tibble [8 × 35] (S3: tbl_df/tbl/data.frame)
## $ _id : int [1:8] 482 484 485 486 487 532 647 659
## $ control_over_life : chr [1:8] "7" "3" "3" "3" ...
## $ Taking_all_things_to_ould_you_say_you_are : chr [1:8] "1" "3" "8" "3" ...
## $ voluntary_activity : chr [1:8] "8" "8" "8" "2" ...
## $ trust_in_groups/Your_family : chr [1:8] "1" "2" "1" "2" ...
## $ formhub/uuid : chr [1:8] "1f37921296654b91b8cc11e152956764" "1f37921296654b91b8cc11e152956764" "1f37921296654b91b8cc11e152956764" "1f37921296654b91b8cc11e152956764" ...
## $ _validation_status :'data.frame': 8 obs. of 0 variables
## $ importance_in_life/Politics : chr [1:8] "1" "3" "2" "3" ...
## $ _uuid : chr [1:8] "199a3066-72a2-48b0-ade1-c186ae6cb0e7" "199a3066-72a2-48b0-ade1-c186ae6cb0e7" "199a3066-72a2-48b0-ade1-c186ae6cb0e7" "199a3066-72a2-48b0-ade1-c186ae6cb0e7" ...
## $ health_self_assessment : chr [1:8] "5" "3" "3" "5" ...
## $ importance_in_life/Friends_and_acquaintances : chr [1:8] "1" "2" "2" "3" ...
## $ _tags :List of 8
## ..$ : list()
## ..$ : list()
## ..$ : list()
## ..$ : list()
## ..$ : list()
## ..$ : list()
## ..$ : list()
## ..$ : list()
## $ trust_in_groups/People_you_know_personally : chr [1:8] "2" "2" "2" "3" ...
## $ _submitted_by : logi [1:8] NA NA NA NA NA NA ...
## $ _xform_id_string : chr [1:8] "aRo4wg5utWT7dwdnQQEAE7" "aRo4wg5utWT7dwdnQQEAE7" "aRo4wg5utWT7dwdnQQEAE7" "aRo4wg5utWT7dwdnQQEAE7" ...
## $ importance_in_life/Family : chr [1:8] "2" "3" "1" "2" ...
## $ trust_in_groups/People_you_meet_for_the_first_time: chr [1:8] "3" "2" "2" "3" ...
## $ meta/instanceID : chr [1:8] "uuid:199a3066-72a2-48b0-ade1-c186ae6cb0e7" "uuid:199a3066-72a2-48b0-ade1-c186ae6cb0e7" "uuid:199a3066-72a2-48b0-ade1-c186ae6cb0e7" "uuid:199a3066-72a2-48b0-ade1-c186ae6cb0e7" ...
## $ trust_in_groups/People_of_another_nationality : chr [1:8] "2" "3" "3" "2" ...
## $ trust_in_groups/People_in_your_neighborhood : chr [1:8] "3" "1" "2" "2" ...
## $ importance_in_life/Religion : chr [1:8] "1" "3" "3" "2" ...
## $ end : chr [1:8] "2021-09-01T21:38:34.035+02:00" "2021-09-01T21:52:25.333+02:00" "2021-09-01T21:53:05.707+02:00" "2021-09-01T21:53:39.141+02:00" ...
## $ locate_hamburg : chr [1:8] "60.924739 -90.682977 0 0" "34.461879 -126.200905 0 0" "48.52047 70.320327 0 0" "64.520727 52.758186 0 0" ...
## $ _submission_time : chr [1:8] "2021-09-01T19:38:34" "2021-09-01T19:52:25" "2021-09-01T19:53:05" "2021-09-01T19:53:39" ...
## $ _notes :List of 8
## ..$ : list()
## ..$ : list()
## ..$ : list()
## ..$ : list()
## ..$ : list()
## ..$ : list()
## ..$ : list()
## ..$ : list()
## $ _attachments :List of 8
## ..$ :'data.frame': 0 obs. of 0 variables
## ..$ :'data.frame': 0 obs. of 0 variables
## ..$ :'data.frame': 0 obs. of 0 variables
## ..$ :'data.frame': 0 obs. of 0 variables
## ..$ :'data.frame': 0 obs. of 0 variables
## ..$ :'data.frame': 1 obs. of 9 variables:
## .. ..$ mimetype : chr "image/png"
## .. ..$ download_small_url : chr "https://kc.correlaid.org/media/small?media_file=api_user%2Fattachments%2F1f37921296654b91b8cc11e152956764%2F40c"| __truncated__
## .. ..$ download_large_url : chr "https://kc.correlaid.org/media/large?media_file=api_user%2Fattachments%2F1f37921296654b91b8cc11e152956764%2F40c"| __truncated__
## .. ..$ download_url : chr "https://kc.correlaid.org/media/original?media_file=api_user%2Fattachments%2F1f37921296654b91b8cc11e152956764%2F"| __truncated__
## .. ..$ filename : chr "api_user/attachments/1f37921296654b91b8cc11e152956764/40c70c77-7d3d-4824-8e0e-43094764a75d/Screenshot 2021-09-0"| __truncated__
## .. ..$ instance : int 532
## .. ..$ download_medium_url: chr "https://kc.correlaid.org/media/medium?media_file=api_user%2Fattachments%2F1f37921296654b91b8cc11e152956764%2F40"| __truncated__
## .. ..$ id : int 3
## .. ..$ xform : int 18
## ..$ :'data.frame': 0 obs. of 0 variables
## ..$ :'data.frame': 0 obs. of 0 variables
## $ importance_in_life/Leisure_time : chr [1:8] "1" "2" "2" "3" ...
## $ start : chr [1:8] "2021-09-01T21:36:49.742+02:00" "2021-09-01T21:36:49.742+02:00" "2021-09-01T21:36:49.742+02:00" "2021-09-01T21:36:49.742+02:00" ...
## $ trust_in_groups/People_of_another_religion : chr [1:8] "2" "3" "3" NA ...
## $ _geolocation :List of 8
## ..$ : num [1:2] 60.9 -90.7
## ..$ : num [1:2] 34.5 -126.2
## ..$ : num [1:2] 48.5 70.3
## ..$ : num [1:2] 64.5 52.8
## ..$ : num [1:2] 62.3 43
## ..$ : num [1:2] 53.5 10
## ..$ : num [1:2] -6.5 85
## ..$ : num [1:2] 53.1 11.1
## $ importance_in_life/Work : chr [1:8] "1" "2" "1" "2" ...
## $ _status : chr [1:8] "submitted_via_web" "submitted_via_web" "submitted_via_web" "submitted_via_web" ...
## $ __version__ : chr [1:8] "vkhZEtuEwyhNgJropgVs7h" "vkhZEtuEwyhNgJropgVs7h" "vkhZEtuEwyhNgJropgVs7h" "vkhZEtuEwyhNgJropgVs7h" ...
## $ trust_in_others : chr [1:8] "2" "2" "2" "2" ...
## $ file_upload : chr [1:8] NA NA NA NA ...
Check out Data wrangling of responses to see how to handle messy column names.
Kobo Administration with kbtbr
With kbtbr
, you can also manage your assets and do other useful administration tasks right from your R console.
Create an Asset
You can also create assets using the create_asset()
method of the Kobo class. This can be useful if you need to create a lot of assets at once.
res <- kobo$create_asset("Question block",
asset_type = "block",
description = "this question block was created with the API.")
res$status_http()
## <Status code: 201>
## Message: Created
## Explanation: Document created, URL follows
response_content <- res$parse("UTF-8") %>% jsonlite::fromJSON()
str(response_content, max.level = 1)
## List of 39
## $ url : chr "https://kobo.correlaid.org/api/v2/assets/avJyi8RUCjQ4RSFA7qdWPG/"
## $ owner : chr "https://kobo.correlaid.org/api/v2/users/api_user/"
## $ owner__username : chr "api_user"
## $ parent : NULL
## $ ancestors : NULL
## $ settings :List of 4
## $ asset_type : chr "block"
## $ date_created : chr "2022-01-24T13:24:29.331033Z"
## $ summary : Named list()
## $ date_modified : chr "2022-01-24T13:24:29.331054Z"
## $ version_id : chr "vZpxcU8qvJ9N6wHSiPsSpv"
## $ version__content_hash : chr "4724ddb07034559d7fb5a3d18288dfb683a2d082"
## $ version_count : int 1
## $ has_deployment : logi FALSE
## $ deployed_version_id : NULL
## $ deployed_versions :List of 4
## $ deployment__identifier : NULL
## $ deployment__links : Named list()
## $ deployment__active : logi FALSE
## $ deployment__data_download_links: Named list()
## $ deployment__submission_count : int 0
## $ report_styles :List of 3
## $ report_custom : Named list()
## $ map_styles : Named list()
## $ map_custom : Named list()
## $ content :List of 3
## $ downloads :'data.frame': 2 obs. of 2 variables:
## $ embeds :'data.frame': 2 obs. of 2 variables:
## $ koboform_link : chr "https://kobo.correlaid.org/api/v2/assets/avJyi8RUCjQ4RSFA7qdWPG/koboform/"
## $ xform_link : chr "https://kobo.correlaid.org/api/v2/assets/avJyi8RUCjQ4RSFA7qdWPG/xform/"
## $ hooks_link : chr "https://kobo.correlaid.org/api/v2/assets/avJyi8RUCjQ4RSFA7qdWPG/hooks/"
## $ tag_string : chr ""
## $ uid : chr "avJyi8RUCjQ4RSFA7qdWPG"
## $ kind : chr "asset"
## $ xls_link : chr "https://kobo.correlaid.org/api/v2/assets/avJyi8RUCjQ4RSFA7qdWPG/xls/"
## $ name : chr "Question block"
## $ assignable_permissions :'data.frame': 3 obs. of 2 variables:
## $ permissions :'data.frame': 3 obs. of 4 variables:
## $ data : chr "https://kobo.correlaid.org/api/v2/assets/avJyi8RUCjQ4RSFA7qdWPG/data/"
Cloning an Asset
In order to clone an asset, you just have to specify its ID, a new name for the cloned asset and its type.
res <- kobo$clone_asset(test_id, "Test survey copy", "survey")
class(res)
## [1] "HttpResponse" "R6"
res$status_http()
## <Status code: 201>
## Message: Created
## Explanation: Document created, URL follows
Parse out the ID of the asset that was created:
response_content <- res$parse("UTF-8") %>% jsonlite::fromJSON()
str(response_content, max.level = 1)
## List of 39
## $ url : chr "https://kobo.correlaid.org/api/v2/assets/ackE4RGzXMjWBei3bRHPbb/"
## $ owner : chr "https://kobo.correlaid.org/api/v2/users/api_user/"
## $ owner__username : chr "api_user"
## $ parent : NULL
## $ ancestors : NULL
## $ settings :List of 3
## $ asset_type : chr "survey"
## $ date_created : chr "2022-01-24T13:04:49.219153Z"
## $ summary :List of 6
## $ date_modified : chr "2022-01-24T13:04:49.219192Z"
## $ version_id : chr "vfAaB99KXQeGf2gMxWA57z"
## $ version__content_hash : chr "f3e28cf31d58b03c955935dedec741d31d4537b8"
## $ version_count : int 1
## $ has_deployment : logi FALSE
## $ deployed_version_id : NULL
## $ deployed_versions :List of 4
## $ deployment__identifier : NULL
## $ deployment__links : Named list()
## $ deployment__active : logi FALSE
## $ deployment__data_download_links: Named list()
## $ deployment__submission_count : int 0
## $ report_styles :List of 3
## $ report_custom : Named list()
## $ map_styles : Named list()
## $ map_custom : Named list()
## $ content :List of 6
## $ downloads :'data.frame': 2 obs. of 2 variables:
## $ embeds :'data.frame': 2 obs. of 2 variables:
## $ koboform_link : chr "https://kobo.correlaid.org/api/v2/assets/ackE4RGzXMjWBei3bRHPbb/koboform/"
## $ xform_link : chr "https://kobo.correlaid.org/api/v2/assets/ackE4RGzXMjWBei3bRHPbb/xform/"
## $ hooks_link : chr "https://kobo.correlaid.org/api/v2/assets/ackE4RGzXMjWBei3bRHPbb/hooks/"
## $ tag_string : chr ""
## $ uid : chr "ackE4RGzXMjWBei3bRHPbb"
## $ kind : chr "asset"
## $ xls_link : chr "https://kobo.correlaid.org/api/v2/assets/ackE4RGzXMjWBei3bRHPbb/xls/"
## $ name : chr "Test survey copy"
## $ assignable_permissions :'data.frame': 9 obs. of 2 variables:
## $ permissions :'data.frame': 8 obs. of 4 variables:
## $ data : chr "https://kobo.correlaid.org/api/v2/assets/ackE4RGzXMjWBei3bRHPbb/data/"
test_clone_id <- response_content$uid
Deploying an asset
To deploy an existing asset, e.g. after cloning or updating:
res <- kobo$deploy_asset(test_clone_id)
class(res)
## [1] "HttpResponse" "R6"
res$status_http()
## <Status code: 200>
## Message: OK
## Explanation: Request fulfilled, document follows
response_content <- res$parse("UTF-8") %>% jsonlite::fromJSON()
str(response_content, max.level = 1)
## List of 5
## $ backend : chr "kobocat"
## $ identifier: chr "https://kc.correlaid.org/api_user/forms/ackE4RGzXMjWBei3bRHPbb"
## $ active : logi TRUE
## $ version_id: chr "vfAaB99KXQeGf2gMxWA57z"
## $ asset :List of 37
Importing XLS forms
You can import an XLS form. This will create a draft survey/form which you could then again deploy using kobo$deploy_asset()
.
res <- kobo$import_xls_form(name = "XLS Form via import", "assets/xls_form_downloaded.xls")
res$status_http()
## <Status code: 201>
## Message: Created
## Explanation: Document created, URL follows
Making it your own: post
and get
kbtbr
is by no means complete. So you might find that some of your use cases are not covered by the existing methods of the Kobo
class. For this purpose, Kobo
as well as the lower-level KoboClient
class expose generic get
and post
functions which should allow you to implement more functionalities on your own. You can check out the existing high-level functions (e.g. get_assets
or clone_asset
) to get ideas how your code should look like. Of course, contributions to kbtbr
are always welcome.