Connect Kobo to anything.
Synopsis: a dockerized python API that sends Kobo submissions and their attachments to other API-enabled applications, changing field names if necessary. It is basically an extension of the KoboToolbox REST Services.
Details: see the docs.
Using the kobo-to-espocrm
endpoint, it is possible to save a Kobo submission as one or more entities in EspoCRM.
- Define which questions in the Kobo form need to be saved in which entity and field in EspoCRM.
- In EspoCRM,
- Create a role (Administration>Roles), set
Access
to the target entity onenabled
, with the permission onyes
toCreate
(if you need to update records, also addRead
andEdit
). - Create an API user (Administration>API Users), give it a descriptive
User Name
, select the previously created role, make sureIs Active
is checked and thatAuthentication Method
isAPI Key
. After saving, you will see a newly created API Key which is needed for the next step.
- Create a role (Administration>Roles), set
- Register a new Kobo REST Service for the Kobo form of interest and give it a descriptive name.
- Insert as
Endpoint URL
https://kobo-connect.azurewebsites.net/kobo-to-espocrm
- In Kobo REST Services, add under
Custom HTTP Headers
:- In
Name
addtargeturl
with in theValue
the EspoCRM URL (for example, https://espocrminstancex.com). - In
Name
addtargetkey
with in theValue
the (newly) created API Key (from EspoCRM API User).
- In
- For each question, add a
Custom HTTP Header
that specifies which Kobo questions responds to which entity and field EspoCRM:- The header
Name
(left) must correspond to the Kobo question name. (You can check the Kobo question name by going into edit mode of the form, open 'Settings' of the specific question and inspect theData Column Name
. Also, the Kobo question names can be found in the 'Data' table with previous submissions. This Kobo question name is different from the Kobo question label and can not contain spaces or symbols (except the underscore).). - The header value (right) must correspond to the EspoCRM entity name, followed by a dot (
.
), followed by the specific field name. Example:Contact.name
. (EspoCRM name is different from the EspoCRM label, similar to the difference between Kobo question name and Kobo question label).
- The header
Important
If you need to send attachments (e.g. images) to EspoCRM, add a Custom HTTP Header
called kobotoken
with your API token (see how to get one).
![](https://private-user-images.githubusercontent.com/26323051/273326597-06de75f3-d02d-4f9f-bb82-db6736542cf5.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUzMjUyNTksIm5iZiI6MTcyNTMyNDk1OSwicGF0aCI6Ii8yNjMyMzA1MS8yNzMzMjY1OTctMDZkZTc1ZjMtZDAyZC00ZjlmLWJiODItZGI2NzM2NTQyY2Y1LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDMlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAzVDAwNTU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTQ2ZWI1MTJlNDZlODIwMTBjYTJiNjZjMzg0MGM2MDRjYTk4OGZjNDk3YmU2MWRkNzkyYzA2YTk3MTgwZGM3ZDgmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.fFXy73km63I2YYkEx4FgSDnWzKJIIg30oeSlprnlroM)
- If you have a question of type
Select Many
(select_multiple
) in Kobo and you want to save it in a field of typeMulti-Enum
in EspoCRM, addmulti.
before the Kobo question name in the header name.- Example header:
multi.multiquestion1
:Entity.field1
- Example header:
- If you have a repeating group of questions in Kobo:
- you will need to save each repeated question in a different field in EspoCRM;
- in the header name:
- add
repeat.
, followed by the repeating group name, followed by a dot (.
); - then add a number to specify the number of the repeated question (starting from 0), followed by a dot (
.
); - then add the name of the repeated question after the number;
- add
- in the header value:
- as before, use the entity name, followed by a dot (
.
), followed by the field name in EspoCRM.
- as before, use the entity name, followed by a dot (
- Example headers:
repeat.repeatedgroup.0.repeatedquestion
:Entity.field1
repeat.repeatedgroup.1.repeatedquestion
:Entity.field2
- Not all repeated questions need to be filled in nor saved to EspoCRM.
- If you need to update a pre-existing record:
- add a question of type
calculate
calledupdaterecordby
in the Kobo form, which will contain the value of the field which you will use to identify the record; - add a
Custom HTTP Header
calledupdaterecordby
with the name of the field that you will use to identify the record.
- add a question of type
- If you need to avoid sending specific submissions to EspoCRM:
- add a question called
skipconnect
in the Kobo form; - whenever its value is
1
(based on some condition), the submission will not be sent to EspoCRM.
- add a question called
Using the kobo-to-121
endpoint, it is possible to save a Kobo submission as a Person Affected (PA) registration in the 121 Portal.
Step by step:
- Define which questions in the Kobo form need to be saved in which field.
- Create a new Kobo REST Service.
- Insert as
Endpoint URL
https://kobo-connect.azurewebsites.net/kobo-to-121
. - For each question, add a
Custom HTTP Header
that specifies to which entity and field it corresponds to.- The header name (left) must correspond to the Kobo column name (not label).
- The header value (right) must correspond to the field name in 121.
Special Headers:
- The headers
url121
is required and corresponds the url of the 121 instance (without trailing/
, so e.g. https://staging.121.global) - Headers
username121
andpassword121
, corresponding to the 121 username and the 121 password respectively, must be included as well. - If
programid
is included as a (select one) question, theXML Value
of the question in Kobo needs to be the corresponding number in the 121 portal, the label can be something else, see below - If
programid
is not included as a question, it needs to be added to the header as a number
See below for an example configuration, in which programId was not included as a question so it is included in the header.
![](https://private-user-images.githubusercontent.com/39266480/262350109-bb7b922b-7a39-4093-b525-456687491ba8.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUzMjUyNTksIm5iZiI6MTcyNTMyNDk1OSwicGF0aCI6Ii8zOTI2NjQ4MC8yNjIzNTAxMDktYmI3YjkyMmItN2EzOS00MDkzLWI1MjUtNDU2Njg3NDkxYmE4LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDMlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAzVDAwNTU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTQ3ZDQ2ZjM1NDhkOTEzOGNkZjgzMGY1ZGQ3ZDZhNDM2YmM0NDgwYzkxZDBhMDY2NmY2OTAxN2ExNzUyZTdlNjQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.vDpEJcJ4oHiu-hLJdLlxc73EtVqqLadKr6aBO9yRKZI)
- The 121 API is currently throttled at 3000 submissions per minute. If you expect to go over this limit, please reach out the the 121 platform team.
- If you would like to define which submissions should and should not be send to EspoCRM, you can use the field
skipconnect
in your Kobo form. If the field is set to1
, the submission will not be send to 121.
If you need to map a lot of questions, creating the headers manually is cumbersome. The /create-kobo-headers
endpoint automates this. It expects 4 query parameters:
system
: required, enum (options: 121, espocrm, generic)kobouser
: your Kobo usernamekobopassword
: your Kobo passwordkoboassetId
: the assed id of the survey (to be found in the url: https://kobonew.ifrc.org/#/forms/`ASSETID`/summary)
In the body you can pass all the headers you want to create as key value pairs, for example:
{
"last_name": "lastName",
"first_name": "firstName",
"household_size": "hhSize"
}
This endpoint assumes the IFRC Kobo server (https://kobonew.ifrc.org
)
See the docs.
cp example.env .env
pip install -r requirements.txt
uvicorn main:app --reload