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.