Posting data submissions using the KOBO Rest API

Hello,

I’m having trouble forming the HTTP request in a correct format as expected for submitting data using the KOBO REST API. I’m trying to this from.net (C#). Could someone please assist me with a simple example of a code snippet of what this would look like?

Thank you!

Hussein

Hi Hussein,
Are you trying to POST an XML or a JSON submission? There are some examples in our API documentation.

If you’ve tried the examples on https://kc.kobotoolbox.org/api/v1/submissions unsuccessfully, could you paste your snippet so we can help troubleshoot?

Best,

Tino

···

On Mon, Dec 7, 2015 at 4:38 AM Hussein Lightwalla hussein.l...@kimetrica.com wrote:

Hello,

I’m having trouble forming the HTTP request in a correct format as expected for submitting data using the KOBO REST API. I’m trying to this from.net (C#). Could someone please assist me with a simple example of a code snippet of what this would look like?

Thank you!

Hussein

You received this message because you are subscribed to the Google Groups “Kobo Users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to kobo-users+...@googlegroups.com.

To post to this group, send email to kobo-...@googlegroups.com.

Visit this group at http://groups.google.com/group/kobo-users.

For more options, visit https://groups.google.com/d/optout.

Hey Tino,

Thanks for your reply. I’ve managed to submit data via CSV files as follows:

var client = new RestClient("https://kc.kobotoolbox.org/api/v1/forms/{pk}/csv_import");
client.Authenticator = new HttpBasicAuthenticator("user_name", "password");
client.AddDefaultUrlSegment("pk", "31045");
string file_path = Server.MapPath("~/myform.csv");
var request = new RestRequest(Method.POST);
request.AddFile("csv_file", file_path);
IRestResponse response = client.Execute(request);

but I still find it difficult with either JSON or XML. I think the main challenge is figuring out how exactly the XML file should be structured or how the JSON should be structured.

Thanks!

···

On Wednesday, December 9, 2015 at 6:56:31 PM UTC+3, Tino Kreutzer wrote:

Hi Hussein,
Are you trying to POST an XML or a JSON submission? There are some examples in our API documentation.

If you’ve tried the examples on https://kc.kobotoolbox.org/api/v1/submissions unsuccessfully, could you paste your snippet so we can help troubleshoot?

Best,

Tino

On Mon, Dec 7, 2015 at 4:38 AM Hussein Lightwalla hussein.l...@kimetrica.com wrote:

Hello,

I’m having trouble forming the HTTP request in a correct format as expected for submitting data using the KOBO REST API. I’m trying to this from.net (C#). Could someone please assist me with a simple example of a code snippet of what this would look like?

Thank you!

Hussein

You received this message because you are subscribed to the Google Groups “Kobo Users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to kobo-users+...@googlegroups.com.

To post to this group, send email to kobo...@googlegroups.com.

Visit this group at http://groups.google.com/group/kobo-users.

For more options, visit https://groups.google.com/d/optout.

1 Like

Hi Hussein,

For importing XML, did you try using the exact format of XML created by KoBoCollect? The default format is

<?xml version='1.0' ?> <your_form_id id="your_form_id"> <formhub><uuid>xxxxxxxxxxxxxxxxxxxxxxx</uuid></formhub><q1>some text</q1><q2>some text</q2><meta><instanceID>uuid:yyyyyyyyy</instanceID></meta> </your_form_id>

Best,
Tino

···

On Mon, Dec 14, 2015 at 7:37 AM Hussein Lightwalla hussein.l...@kimetrica.com wrote:

Hey Tino,

Thanks for your reply. I’ve managed to submit data via CSV files as follows:

var client = new RestClient("[https://kc.kobotoolbox.org/api/v1/forms/{pk}/csv_import](https://kc.kobotoolbox.org/api/v1/forms/%7Bpk%7D/csv_import)");
client.Authenticator = new HttpBasicAuthenticator("user_name", "password");
client.AddDefaultUrlSegment("pk", "31045");
string file_path = Server.MapPath("~/myform.csv");
var request = new RestRequest(Method.POST);
request.AddFile("csv_file", file_path);
IRestResponse response = client.Execute(request);

but I still find it difficult with either JSON or XML. I think the main challenge is figuring out how exactly the XML file should be structured or how the JSON should be structured.

Thanks!

On Wednesday, December 9, 2015 at 6:56:31 PM UTC+3, Tino Kreutzer wrote:

Hi Hussein,
Are you trying to POST an XML or a JSON submission? There are some examples in our API documentation.

If you’ve tried the examples on https://kc.kobotoolbox.org/api/v1/submissions unsuccessfully, could you paste your snippet so we can help troubleshoot?

Best,

Tino

On Mon, Dec 7, 2015 at 4:38 AM Hussein Lightwalla hussei...@kimetrica.com wrote:

Hello,

I’m having trouble forming the HTTP request in a correct format as expected for submitting data using the KOBO REST API. I’m trying to this from.net (C#). Could someone please assist me with a simple example of a code snippet of what this would look like?

Thank you!

Hussein

You received this message because you are subscribed to the Google Groups “Kobo Users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to kobo-us...@googlegroups.com.

To post to this group, send email to kobo...@googlegroups.com.

Visit this group at http://groups.google.com/group/kobo-users.

For more options, visit https://groups.google.com/d/optout.

You received this message because you are subscribed to the Google Groups “Kobo Users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to kobo-users+...@googlegroups.com.

To post to this group, send email to kobo-...@googlegroups.com.

Visit this group at https://groups.google.com/group/kobo-users.

For more options, visit https://groups.google.com/d/optout.

Hey Tino,

I’ll give this a shot. Thanks!

Kind regards,

Hussein

···

On Wednesday, December 30, 2015 at 7:24:03 PM UTC+3, Tino Kreutzer wrote:

Hi Hussein,

For importing XML, did you try using the exact format of XML created by KoBoCollect? The default format is

<?xml version='1.0' ?> <your_form_id id="your_form_id"> <formhub><uuid>xxxxxxxxxxxxxxxxxxxxxxx</uuid></formhub><q1>some text</q1><q2>some text</q2><meta><instanceID>uuid:yyyyyyyyy</instanceID></meta> </your_form_id>

Best,
Tino

On Mon, Dec 14, 2015 at 7:37 AM Hussein Lightwalla hussein.l...@kimetrica.com wrote:

Hey Tino,

Thanks for your reply. I’ve managed to submit data via CSV files as follows:

var client = new RestClient("[https://kc.kobotoolbox.org/api/v1/forms/{pk}/csv_import](https://kc.kobotoolbox.org/api/v1/forms/%7Bpk%7D/csv_import)");
client.Authenticator = new HttpBasicAuthenticator("user_name", "password");
client.AddDefaultUrlSegment("pk", "31045");
string file_path = Server.MapPath("~/myform.csv");
var request = new RestRequest(Method.POST);
request.AddFile("csv_file", file_path);
IRestResponse response = client.Execute(request);

but I still find it difficult with either JSON or XML. I think the main challenge is figuring out how exactly the XML file should be structured or how the JSON should be structured.

Thanks!

On Wednesday, December 9, 2015 at 6:56:31 PM UTC+3, Tino Kreutzer wrote:

Hi Hussein,
Are you trying to POST an XML or a JSON submission? There are some examples in our API documentation.

If you’ve tried the examples on https://kc.kobotoolbox.org/api/v1/submissions unsuccessfully, could you paste your snippet so we can help troubleshoot?

Best,

Tino

On Mon, Dec 7, 2015 at 4:38 AM Hussein Lightwalla hussei...@kimetrica.com wrote:

Hello,

I’m having trouble forming the HTTP request in a correct format as expected for submitting data using the KOBO REST API. I’m trying to this from.net (C#). Could someone please assist me with a simple example of a code snippet of what this would look like?

Thank you!

Hussein

You received this message because you are subscribed to the Google Groups “Kobo Users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to kobo-users+...@googlegroups.com.

To post to this group, send email to kobo...@googlegroups.com.

Visit this group at http://groups.google.com/group/kobo-users.

For more options, visit https://groups.google.com/d/optout.

You received this message because you are subscribed to the Google Groups “Kobo Users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to kobo-users+...@googlegroups.com.

To post to this group, send email to kobo...@googlegroups.com.

Visit this group at https://groups.google.com/group/kobo-users.

For more options, visit https://groups.google.com/d/optout.

I’m having some trouble submitting data programmatically using JSON. I imagine it is because I’m not constructing the JSON properly. Here’s my script for a form that has a single question “Name_Entered”:

import requests

headers = {"Content-Type": "application/json",
           'Authorization': 'Token <MY_TOKEN>'
           }
json = {
        "Name_Entered": "Test",
        "meta": {
            "instanceID": "uuid:8992c3c2-3418-4ba9-a8e2-b00e03ea36b6"
        }
    }

data = {"id": "<MY_FORM_ID>", "submission": json}
response = requests.post("https://<KC URL>/api/v1/submissions.json", data=data, headers=headers)

print(response.text)

I get the following response:
{"detail":"JSON parse error - No JSON object could be decoded"}

Can someone guide me?

Hi @ks_1, unfortunately submitting data with JSON can be unpredictable — I’m also battling. I would recommend rather using XML as that’s how we handle it on the backend. You can see how we handled submission duplication here.

It isn’t pretty, but I adapted what I did there to try and meet your current need. You’ll just need to adjust things to make it work for you and likely use Python’s xml.etree library as I did to programmatically update the xml tree. In this example I’ve just used the submission’s XML structure as a template (you can see that if you navigate to /api/v2/assets/{asset_uid}/data.xml)

You can give this a try:

import io
import requests
import uuid
from datetime import datetime

BASE_URL = 'https://kc.kobotoolbox.org'
SUMISSION_URL = f'{BASE_URL}/api/v1/submissions'
TOKEN = '<TOKEN>'

def format_openrosa_datetime():
    return datetime.now().isoformat('T', 'milliseconds')

def create_xml_submission(data, _uuid):
    return f'''
    <atewgEAX2sG2ibzvs6dTHV id="atewgEAX2sG2ibzvs6dTHV" version="1 (2021-03-25 18:06:48)">
        <formhub>
            <uuid>8db71a06863349c6abe8bb5edf6d4b4e</uuid>
        </formhub>
        <start>{format_openrosa_datetime()}</start>
        <end>{format_openrosa_datetime()}</end>
        <answer_me>{data}</answer_me>
        <__version__>vWG8dR5D2BhooJjhQ8zrqy</__version__>
        <meta>
            <instanceID>uuid:{_uuid}</instanceID>
        </meta>
    </atewgEAX2sG2ibzvs6dTHV>
    '''.encode()

def submit_data(data):
    _uuid = str(uuid.uuid4())
    file_tuple = (_uuid, io.BytesIO(create_xml_submission(data, _uuid)))
    files = {'xml_submission_file': file_tuple}
    headers = {'Authorization': f'Token {TOKEN}'}
    res = requests.Request(
        method='POST', url=SUMISSION_URL, files=files, headers=headers
    )
    session = requests.Session()
    res = session.send(res.prepare())

    if res.status_code == 201:
        return 'Success 🎉'
    return 'Something went wrong 😢'

if __name__ == '__main__':
    res = submit_data('hello world')
    print(res)

If you enter your token there it should send data to my form.

2 Likes

Thanks, it works!! :smiley:
How do I send attachments? File/photo etc?

2 Likes

@ks_1 you can submit files the same way by just extending the submit_data() method above. Something like this:

def submit_data(data, file_name):
    ...
    another_file_tuple = (file_name, open(file_name, 'rb'))
    files = {'xml_submission_file': file_tuple, file_name: another_file_tuple}
    ...

Note that if you look at the network tab in your browser dev tools while submitting data through Enketo, the request data will give you a rough idea how to do what you’re wanting.

2 Likes

Thanks a lot @Josh… You’re a lifesaver.

2 Likes

It doesn’t work for me.
return error 404

I combined this with an excel file to allow for forms with different heading labels, see here:

Thanks for the inspiration!

1 Like

@ralphthompson, :clap: :heart: :partying_face:

That’s great, could you share with us an example for sharing multiple images

Thank you; it works. Now my question is, if I have name and age, how can I pass the data?